Is reusing a WebGLProgram a good idea? - webgl

Instead of creating new WebGlProgram's using gl.createProgram() is it a good idea to keep reusing one?
I am listing the steps that I should be doing if I am to reuse one:
AttachShader(s): in my case I need to attach a new Fragment shader only. (Question: Can I hang on to a compiled shader?)
linkProgram
useProgram
getAttribLocation
getUniformLocation

What are you trying to do? 99.9% of all GPU apps make shader programs and are done. They might make 1, they might make 5000, but they aren't ever in a position where they would even need to consider your question. So what are you really trying to do?
Those few apps that do allow you to edit shaders (shadertoy, glslsandbox, vertexshaderart, ...) either make new ones and delete old or reuse. There's no benefit to one or the other it's just a matter of style.
Yes you can hold on to shaders. You can use shaders with multiple programs. It's common to do so.
If you change a shader it won't affect a program unless/until you relink that program with gl.linkProgram. Anytime you call gl.linkProgram and it's successful all your previous uniform locations for that program are obsolete and you have to query new ones.

Related

webGL,SLGL? where should I start with this code

I am familiar with C or C++
However, I am a quite newbie for WEBGL and GLSL.
It might be too basic or silly question though... I appreciate you give me some hints.
I found this source code which makes the great CG graphics.
I want to compile this by myself, However honestly saying I am not sure what it is , and what with compiler I can compile and make this work .
#define R rotate2D
for(float i,e,g,s;i++<1e2;g+=e*.2)
{
vec3 n,p=vec3((FC.xy-.5*r)/r.y*g,g-4.);
p.zy*=R(.4);
p.z+=t;
e=p.y;
for(s=1.;s<6e3;s+=s)p.xz*=R(s),n.xz*=R(s),n+=cos(p*s),e+=dot(sin(p.xz*s),r/r/s/3.);
n.y=1.;
n=normalize(n);
e-=snoise2D(p.xz*40.)*n.y*n.y*.4;
o-=exp(-e*9.-5.);
}
o++;
So at first, I started to learn about webGL.
And finished learning basic webGL
However I cant make it work with webGL.
Next, I started to learn about SLGL on unity,,, however it's not hit the spot.
What should I learn to compile this???
This looks a piece of a GLSL shader, and you would compile that with gl.compileShader()
But it's incomplete. First of all to be completely compilable it needs a main function that sets gl_FragColor. And I see a reference to snoise2D and rotate2D which should be functions, but are missing. And a least a few local undefined variables like FC and r. So without those pieces, this won't compile.
If you can solve those issues, you should be able to plug into something like ShaderToy without have to invent a whole WebGL application from scratch. But if this shader is meant to interact with specific geometry that might not work at all.
It's hard to advise more without more info on what this is, how its intended and what all that single letter variable names are supposed to mean.

Correct way to import and create many large sprites: SpriteKit

Despite reading through much of Apple's docs and reading through their forums and watching their WWDC videos, I seem to have missed the steps required to utilise the texture packing and performance of Sprite Kit for making many large-ish Sprites.
Imagine 100 different sprite images, for 100 different sprites. If each image is 256x256 pixels, they're going to take up more than one SpriteSheet at 2048x2048. And let's imagine that's the limit, rather than 4096x4096, just so it's understood that more than one spritesheet is going to be required.
There might be as many as 20 different sprites on screen at any given time. So performance is a consideration.
How to import these images and then create these sprites in the manner SpriteKit intends for its texture packing and performance considerations of in game use?
Just a specific link to Apple recommended absolute steps will be fine. I must have just skimmed right over it.
Apple's new docs go this far:
Which completely fails to convey:
Import folder, or images?
Import to WHERE within the project?
Load and reference them, how?
So let me see if I can reasonably answer your question. Please keep in mind that while I have used SpriteKit, I'm not a big fan of it. And when I did use it, I did not use any of the tools Apple provided (eg. SKTextureAtlas, sks files, etc). Nevertheless, this should still be applicable. Best practices as per Apple? I have no idea.
Question: Import folder, or images?
If you use Xcode's means of generating atlases, you Add Files... to your project a folder named XYZ.atlas, where XYZ will be the texture name. This folder contains all of your textures which will be in the atlas.
Question: Import to WHERE within the project?
Just has to be in your project. But you should have some organization Group hierarchy in your project file.
Question: Load and reference them, how?
An example of loading would be something like (yeah, I know boo, Obj-C):
self.myTextureAtlas = [SKTextureAtlas atlasNamed:#"MyTexture"];
Inevitably, you will want access to the actual textures and you'll need to do something like:
self.tex0 = [self.myTextureAtlas textureNamed:#"tex0"];
A good tutorial is here: https://www.raywenderlich.com/45152/sprite-kit-tutorial-animations-and-texture-atlases
Here is also a screenshot that shows the .atlas folder. It also shows a couple of tool generated atlas files.
So here you can see I have 2 Groups which are references to folder MyTexture.atlas and ProgressBar.atlas. In game, they will be called MyTexture and ProgressBar.
I have also included, just as an example the same atlases, but pre-built. You would not have both in your project, I only used it to show what including a pre-built would loo like. I generated them using TexturePacker. I'll get into why this may be a better option later on. TexturePacker also can create SpriteKit atlases instead of the atlas PNG.
In reality, an atlas is really just a texture with sub-textures are associated with it. The sub-textures are X/Y/W/H sections of the texture. The actual memory for the texture is "held" by the atlas. Understanding what an atlas is is a useful thing, because it allows you to think through how you would support it if you had to implement it yourself. Or enhance it.
Now let's go over how you would use this altogether to do something useful.And for this you're going to need a texture manager (aka TextureManager), sprite manager (aka SpriteManager) and a manifest of some sort.
The manifest is really some form of association between "sprite name" to atlas:sub texture pair. For example:
{
"progressbar": {
"atlas": "ProgressBar",
"subtexture": progressbarbacking"
},
"progressbarfillr": {
"atlas": "ProgressBar",
"subtexture": progressbarfillr"
}
}
In this case it is some JSON, but you can have whatever format you want. When I build my games, I have a build assets phase which generates all my textures and from that, builds a manifest. This manifest tells me not only what textures exist, but is used later on to find the correct association of a "sprite name" to the actual atlas and sub texture. "sprite name" is just some name you have associated meaning. It could be "zombie" for example.
You use a TextureManager as your asynchronous loader. In addition, it is your inventory manager of all your textures. As an inventory manager, it will prevent you from double loading textures and also give you the correct reference to textures/atlases when requested (if they exist).
You would use the SpriteManager to create a new SKSpriteNode using the data from the manifest. For example:
SKSpriteNode *progressBar = [[SpriteManager sharedInstance] createSprite:#"progressbar"];
Here I've made it a singleton. Use whatever implementation you want. If you hate singletons, that is fine, this is just an example. You'll note that it returns a SKSpriteNode. I see a lot of people making subclasses from SKSpriteNodes. I never do this. To me, the graphic component is always a "has a". However, if you are doing an "is a", you can still do this. You just need to feed in the class you need. I'm considering the way of handling that out of scope for this question.
Now if you look at the manifest, you'll notice that progressbar is associated with an atlas named ProgressBar and a sub texture named progressbarbacking. To get the texture you need, you'd have some implementation code in SpriteManager like:
// NOTE the literal names would be variables which contained the unpacked association from progressbar
// literal strings are used to make the idea easier to follow
SKTextureAtlas *atlas = [[TextureMaanger sharedInstance] findAtlasNamed:#"ProgressBar"];
//Error check of course
SKTexture *tex = [atlas textureNamed:#"progressbarbacking"];
// Error check of course
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithTexture:tex];
Or perhaps you would just have a call:
SKTexture *tex = [[TextureManager] sharedInstance] texNamed:#"progressbarbacking" atlas:#"ProgressBar"];
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithTexture:tex];
And there you have it. A means to get sprites from atlases.
Best practices as per Apple? Dunno, but it is along the lines of what I do.
Some people will complain that there will be dictionaries involved and some of this will be "slow". And yes, there is a penalty for this. And reality, I don't use a dictionary for this either, but it is easier to get the idea across as the dictionary. Also keep in mind that I consider the usage of this to occur during loading phases and very little during game play, if at all. One of the tricks to performant games is pre-loading all or as much of the data you need prior to actual game play.
Oh, going to why I pre-build the atlases. So part of your question was organization of textures to atlas. And that is why. I like to see the generated atlas and understand what the size is and what is in it. Additionally it makes downloadable atlases easier.
As an optimization, you would want to try and put textures in which are all drawn relatively the same time. For example, it would make sense to have all HUD items in the same atlas versus mixing HUD with background.

Why does VkAccessFlagBits include both read bits and write bits?

In vulkan.h, every instance of VkAccessFlagBits appears in a pair that contains a srcAccessMask and a dstAccessMask:
VkAccessFlags srcAccessMask;
VkAccessFlags dstAccessMask;
In every case, according to my understanding, the purpose of these masks is to help designate two sets of operations, such that results of operations in the first set will be visible to operations in the second set. For instance, write operations occurring prior to a barrier should not get hung up in caches but should instead propagate all the way to locations from which they can be read after the barrier. Or something like that.
The access flags come in both READ and WRITE forms:
/* ... */
VK_ACCESS_SHADER_READ_BIT = 0x00000020,
VK_ACCESS_SHADER_WRITE_BIT = 0x00000040,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100,
/* ... */
But it seems to me that srcAccessMask should probably always be some sort of VK_ACCESS_*_WRITE_BIT combination, while dstAccessMask should always be a combination of VK_ACCESS_*_READ_BIT values. If that is true, then the READ/WRITE distinction is identical to and implicit in the src/dst distinction, and so it should be good enough to just have VK_ACCESS_SHADER_BIT etc., without READ_ or WRITE_ variants.
Why are there READ_ and WRITE_ variants, then? Is it ever useful to specify that some read operations must fully complete before some other operations have begun? Note that all operations using VkAccessFlagBits produce (I think) execution dependencies as well as memory dependencies. It seems to me that the execution dependencies should be good enough to prevent earlier reads from receiving values written by later writes.
While writing this question I encountered a statement in the Vulkan specification that provides at least part of an answer:
Memory dependencies are used to solve data hazards, e.g. to ensure that write operations are visible to subsequent read operations (read-after-write hazard), as well as write-after-write hazards. Write-after-read and read-after-read hazards only require execution dependencies to synchronize.
This is from the section 6.4. Execution And Memory Dependencies. Also, from earlier in that section:
The application must use memory dependencies to make writes visible before subsequent reads can rely on them, and before subsequent writes can overwrite them. Failure to do so causes the result of the reads to be undefined, and the order of writes to be undefined.
From this I surmise that, yes, the execution dependencies produced by the Vulkan commands that involve these access flags probably do free you from ever having to put a VK_ACCESS_*_READ_BIT into a srcAccessMask field--but that you might in fact want to have READ_ flags, WRITE_ flags, or both in some of your dstAccessMask fields, because apparently it's possible to use an explicit dependency to prevent read-after-write hazards in such a way that write-after-write hazards are NOT prevented. (And maybe vice-versa?)
Like, maybe your Vulkan will sometimes decide that a write does not actually need to be propagated all the way through a particular cache to its final specified destination for the sake of a subsequent read operation, IF Vulkan happens to know that that read operation will simply read from that same cache, saving some time? But then a second write might happen, and write to a different cache, and there'll be two caches left in a race (with the choice of winner undefined) to send their two values to the same spot. Or something? Maybe my mental model of these caches is entirely wrong.
It is fairly solidly established, at least, that memory barriers are confusing.
Let's go over all the possibilities:
read–read — well yeah that one is pretty useless. Khronos seems to agree #131 it is pointless value in src (basically equivalent to 0).
read–write — execution dependency should be sufficient to synchronize without this. Khronos seems to agree #131 it is pointless value in src (basically equivalent to 0).
write–read — that's the obvious and most common one.
write–write — similar reason to write–read above. Without it the order of the writes would be undefined. It is a bit pointless for most situations to write something you haven't even read in between. But hey, now you have a way to synchronize it.
You can provide bitmask of more of these masks to both src and dst. In which case it makes sense to have both masks for driver to sort the dependencies out for you. (I don't expect performance overhead from this on API level, so it is allowed as convenience)
From API design perspective, it could mean adding different enum for srcAccess. But perhaps _READ variants could just be forbidden in srcAccess through "Valid Usage", making this argument weak. The src == READ variant might have been kept, because it is benign.

Multisampling in SharpDX

So I have recently started using SharpDX, and have stumbled into a problem. I have no idea how to get SharpDX to multisample. I have found two things related; you can specify a SampleDescription when creating the SwapChainDescription, but any input other than (1, 0) throws a Wrong Parameter exception.
The other thing I found was SamplerState, which I put on my pixel shader, didn't do anything. I played around a lot with the parameters, but there was no visible change whatsoever.
I am sure I am missing something, but without any previous directX knowlegde I have no idea really what exactly to look for.
This will come in handy in your case:
int maxsamples = Device.MultisampleCountMaximum;
int res = device.CheckMultisampleQualityLevels(SharpDX.DXGI.Format.R8G8B8A8_UNorm, samplecount);
If res returns 0 then this Sample count is not supported.
Also please note that some options are not compatible, so if you create your SwapChain with:
sd.Usage = (other usages) | Usage.UnorderedAccess;
You are not allowed to use multisampling.
Another very useful technique to spot the problems for those errors:
Create your device with DeviceCreationFlags.Debug
In your startup project properties (debug section), tick "Enable native code debugging".
Any API call that fails will give you an error description in the debug output window.
I had the same problem, could not get Multisampling to work until I enabled the debugging and got a good hint (really wished I had done this hours ago and saved a whole lot of testing!).
Initially I read somewhere that the DepthStencilBuffer had the same SampleDescription as the Render texture - but I'm not so sure as it appears to work without this as a quick test just showed.
The thing for me was to create the DepthStencilView with a DepthStencilViewDescription that has "Dimension = DepthStencilViewDimension.Texture2DMultisampled".
Just a heads up on when you are doing multisampling.
When you set your rendertarget, if passing a rendertarget and depthstencil, you need to ensure they both have the same multisampling level.
So, for rendering to the backbuffer you have defined with MSAA, you will need to create a depth buffer with the same MSAA level.
BUT, if you are have a rendertarget that will be a texture that is fed back into the pipeline, you can define a non MSAA texture and a NON MSAA depth buffer, which is handy as you can use a sampler on the texture (you cant use a normal sampler for a MSAA Resource texture).
Most of this info maybe not new for you.

How to make a change in Qualcomm's Vuforia Sample App

I have been looking through the threads at the Qualcomm Forums but no luck since I don't know exactly how to look for what I want.
I'm working with the ImageTargets Sample for iOS and I want to change the teapot to another image (a text rather) I had.
I already have the render and I got the .h using opengl library but I can't figure out what do I need to change to make this work and since this is the very basic and I haven't been able to make it work I really haven't ventured to try anything else.
Could anyone please help me out?
I would paste code here but it's a whole project so I don't know exactly what to put if needed please let me know.
If the case is still valid, here's what you have to do:
get header file for 3D object
get texture image for this object
in EAGLView.mm make this changes:
import "yourobject3d.h"
add your texture to textureFilenames array(this should be at the begining of EAGLView
eventually take care about kObjectScale (by deafult it was about 3.0f, for one object I did have to change it even up to 120.0f)
in setup3dObjects method assign proper arrays of vertices/normals/texture coords (check in "yourobject3d.h" file for proper arrays and naming) to Object3D *object
make this change in renderFrameQCAR
//glDrawElements(GL_TRIANGLES, obj3D.numIndices, GL_UNSIGNED_SHORT, (const GLvoid*)obj3D.indices);
glDrawArrays(GL_TRIANGLES, 0, obj3D.numVertices);
I believe that is all... if something take a look at Vuforia's forum, i.e. here: https://developer.vuforia.com/node/2047669
NOTE: default teapot.h does (!) have indices, which are not present in banana.h (from comment below) so take care about that too
Have a look at the EAGLView.mm file. There you'll have to load the textures (images) and 3d objects (you'll need to import your .h instead of teapot.h and modify setup3dObjects accordingly).
They are finally rendered by calling the renderFrameQCAR function.
Actually, teapot is not an image. It's a 3D model stored in .h format which includes Vertices, Normals, and Texture coordinates. You should have a good knowledge of OpenGL ES to understand those codes in sample app.
An easier way to change the 3D model to whatever you want is to use a rendering engine which facilitates the drawing and rendering stuffs and you don't need to bother OpenGL APIs. I've done it with jPCT-AE for Android platform but for iOS there is a counterpart called OpenFrameworks engine. It has some plugins to load 3Ds or MD2 files and since it's written in C++ you can easily integrate it with QCAR.
This is a short video of my result with jPCT and QCAR:
Qualcomm Vuforia + jPCT-AE test video

Resources