This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
16
Developing ENIGMA / Graphics system compatiblity
« on: July 29, 2014, 06:52:40 pm »
We have come to a point (we came to it before actually) where not only compatibility with GM:S hurts us, but sometimes even compatibility between our graphics systems hurts us. Like if we want GL3 and D3D11 support GL1 and D3D9, then we cannot in most cases improve those two systems. We are stuck with crappy FFP functionality. And while 99% I can remake in shaders and thus make it look virtually the same, there are bigger problems with D3D and GL, which at the very core actually incompatible (although GL4 and DX11 is a lot closer together).
So the question I ask is this:
Should we create graphics system specific functions? Like would it be valid, to have a specific function in GL3 that isn't in GL1 or D3D9? That is actually already the case with shaders. The GL3 shader code will never run on GL1 and all the functions I made for the shader system will never be compatible with GLSL1.0. Recently I added some culling functions in GL, which I can run in both GL1 and GL3, but Robert said he doesn't have that capability in D3D. While I proposed a way he could do basically the same thing, it might not be identical, and in some other cases we might not find a solution at all.
Right now there are stuff like "d3d_set_point_size" which I myself added because I needed it. And I still need the functionality, but in GL3 it's done via shaders. So unless I implement this in our GL3 default shader, I won't be able to support that function in that form. But then the shader gets more and more bloated for functions people will almost never use. And I don't even need it in my default shader. I need it in a custom one. So there is no reason to have that function in GL3, but there could be a different one - d3d_enable_point_size - because in GL3 you glEnable() point size and then use gl_point_size in vertex shader to specify the size. So both systems will have the same functionality, but will use two different functions and will require different ways to use them.
So this is why having several graphics systems is such a pain. This is probably why YYG just writes one GL code and uses Angle. My propositions:
1) Keep GL1.1 compatible with older GM (so 8.1 or less). So you can load an older GM game and run it without much hassle.
2) Keep GL3.3 at least partly compatible with GM:S. This will never be possible, but we can reduce the amount of problems users might have when converting their projects. But this even include things like shaders, which are mostly compatible between ENIGMA and GM:S. But other than that, we shouldn't strive for 100% compatibility. Only when it makes sense.
3) Both systems could have functions that are not in the other. But to reduce confusion we must show that the project uses functions not available in that graphics system. We could of course make it just error out, but I would suggest it runs anyway and just trow a warning. Although erroring at compile time is also an option, because I expect users to use only one graphics system for their projects and save using EGM, so their choice of graphics system is always saved too.
I will personally work only on GL3.3 and improve that. I implement something in GL1.1 only if it's very easy to do so. Otherwise I will leave empty functions with printf warnings or not code functions at all (so it errors when used), but this requires separate headers. As I won't implement graphics system specific functions in "general" headers.
So the question I ask is this:
Should we create graphics system specific functions? Like would it be valid, to have a specific function in GL3 that isn't in GL1 or D3D9? That is actually already the case with shaders. The GL3 shader code will never run on GL1 and all the functions I made for the shader system will never be compatible with GLSL1.0. Recently I added some culling functions in GL, which I can run in both GL1 and GL3, but Robert said he doesn't have that capability in D3D. While I proposed a way he could do basically the same thing, it might not be identical, and in some other cases we might not find a solution at all.
Right now there are stuff like "d3d_set_point_size" which I myself added because I needed it. And I still need the functionality, but in GL3 it's done via shaders. So unless I implement this in our GL3 default shader, I won't be able to support that function in that form. But then the shader gets more and more bloated for functions people will almost never use. And I don't even need it in my default shader. I need it in a custom one. So there is no reason to have that function in GL3, but there could be a different one - d3d_enable_point_size - because in GL3 you glEnable() point size and then use gl_point_size in vertex shader to specify the size. So both systems will have the same functionality, but will use two different functions and will require different ways to use them.
So this is why having several graphics systems is such a pain. This is probably why YYG just writes one GL code and uses Angle. My propositions:
1) Keep GL1.1 compatible with older GM (so 8.1 or less). So you can load an older GM game and run it without much hassle.
2) Keep GL3.3 at least partly compatible with GM:S. This will never be possible, but we can reduce the amount of problems users might have when converting their projects. But this even include things like shaders, which are mostly compatible between ENIGMA and GM:S. But other than that, we shouldn't strive for 100% compatibility. Only when it makes sense.
3) Both systems could have functions that are not in the other. But to reduce confusion we must show that the project uses functions not available in that graphics system. We could of course make it just error out, but I would suggest it runs anyway and just trow a warning. Although erroring at compile time is also an option, because I expect users to use only one graphics system for their projects and save using EGM, so their choice of graphics system is always saved too.
I will personally work only on GL3.3 and improve that. I implement something in GL1.1 only if it's very easy to do so. Otherwise I will leave empty functions with printf warnings or not code functions at all (so it errors when used), but this requires separate headers. As I won't implement graphics system specific functions in "general" headers.
17
Developing ENIGMA / Redundancy
« on: July 28, 2014, 12:02:16 pm »
Why do we have "EGMenable.h", "GL3enable.cpp" and some of the same functionality in "GL3d3d.h"? I am now removing all deprecated functions from GL3, which sadly involves most of the stuff in the first to files (like alpha testing). I will see if I can implement them in the shader, but I don't really want too, as they are rarely used and can be implemented manually in a custom shader.
What's your all take on these functions?
What's your all take on these functions?
18
Developing ENIGMA / Accessing with types and passing by strong reference
« on: July 14, 2014, 06:42:19 am »
I think I have made a topic about this before, but I can't remember, so here it goes again, with some new insights.
As we all know in GM every ID for resources (LGM like sprites, background or runtime like ds_grid) is an integer. I always lowed this in GM, because it makes learning A LOT easier, as in C++ this usually involves pointers or references. But this makes code messy, as the engine doesn't know if the number "5" gives is an ID for sprite or a background. Here are some suggestions:
1) I previously suggested we just use classes (both return and pass to functions), as the user wouldn't know any better. He might be confused why "sprite_id*5" doesn't work, but that shouldn't work in any case. But it does mean problems with variables. By default every variable is a "variant", which means "variant" would have to cast to "Sprite" and "Background" and so on. I don't think that is possible, as it might only cast to "*Sprite" at best, and that would be required for this to work:
2) Create a typedef which basically wraps integers. This seems like the best option and in my ultimate wisdom I didn't come up with it before. Basically we would have a type define as "Sprite_ID" and it would basically be an integer in every shape or form. The only difference is that if I pass a number 5 of type "Sprite_ID", then I know it's a sprite ID, not something else. The problem here is that we still need to cast variant to these types. Like this:
3) Another way which would only partly fix this, is to have a unified ID vector. Like all sprites, backgrounds, rooms, instances etc. would use the same map or vector. This would mean every ID would be 100% unique, and thus identifiable with a certain kind of resource. But this greatly reduces the maximum of amount of resources possible (maximum integer can hold, which might not be enough if they include all instance of all rooms and even all tiles).
But I don't really suggest totally getting rid of all those functions. I think they can stay for the time being as they are required for GM compatibility, and we are quite used to them. What I actually need this functionality for is new stuff, especially extensions. Like I am in process of making a GUI extension (something on the lines mentioned in the wiki here: http://enigma-dev.org/docs/Wiki/GUI_Functions) and I want to support these two case:
One way to fix this would be to ask users to code in C++. So they could in fact write:
In my case maybe the third option could work, as I basically would have a GUI_MAP having all the GUI elements which would mean that every one will have a unique ID. But I wouldn't be able to use this for other resources like sprites or backgrounds.
So this topic is mostly addressed to Josh, as he deals with EDL. How would you propose to fix this?
As we all know in GM every ID for resources (LGM like sprites, background or runtime like ds_grid) is an integer. I always lowed this in GM, because it makes learning A LOT easier, as in C++ this usually involves pointers or references. But this makes code messy, as the engine doesn't know if the number "5" gives is an ID for sprite or a background. Here are some suggestions:
1) I previously suggested we just use classes (both return and pass to functions), as the user wouldn't know any better. He might be confused why "sprite_id*5" doesn't work, but that shouldn't work in any case. But it does mean problems with variables. By default every variable is a "variant", which means "variant" would have to cast to "Sprite" and "Background" and so on. I don't think that is possible, as it might only cast to "*Sprite" at best, and that would be required for this to work:
Code: (edl) [Select]
sprite_id = spr_some_guy;
We should pass references anyway, as I don't want to copy data in this instance.2) Create a typedef which basically wraps integers. This seems like the best option and in my ultimate wisdom I didn't come up with it before. Basically we would have a type define as "Sprite_ID" and it would basically be an integer in every shape or form. The only difference is that if I pass a number 5 of type "Sprite_ID", then I know it's a sprite ID, not something else. The problem here is that we still need to cast variant to these types. Like this:
Code: (edl) [Select]
a = 5; //Here variant of type variant with value 5
a = spr_some_guy; //Here the variant needs to be cast, which I don't know if is even possible taking into account the POD nature
Also, this would mean we ALWAYS would have to use sprite name or the ID returned by sprite_add, to reference this sprite. This means we couldn't just load an integer from a file, and then use it as an ID. But the user shouldn't be doing that anyway, as he cannot know which ID the sprite will be assigned to. So I think we are okay in this regard. Slightly break GM compatibility, but greatly increases the future prospects we could have. Like we could replace draw_sprite, draw_background and draw_surface with one function - draw_image. And we could even allow draw_sprite's image frame argument to be supported via an overload.3) Another way which would only partly fix this, is to have a unified ID vector. Like all sprites, backgrounds, rooms, instances etc. would use the same map or vector. This would mean every ID would be 100% unique, and thus identifiable with a certain kind of resource. But this greatly reduces the maximum of amount of resources possible (maximum integer can hold, which might not be enough if they include all instance of all rooms and even all tiles).
But I don't really suggest totally getting rid of all those functions. I think they can stay for the time being as they are required for GM compatibility, and we are quite used to them. What I actually need this functionality for is new stuff, especially extensions. Like I am in process of making a GUI extension (something on the lines mentioned in the wiki here: http://enigma-dev.org/docs/Wiki/GUI_Functions) and I want to support these two case:
Code: (edl) [Select]
button_set_image(button,spr_button1);
button_set_image_hover(button,bg_button1);
Instead of:Code: (edl) [Select]
button_set_image_sprite(button,spr_button1);
button_set_image_hover_background(button,bg_button1);
And the second case is with my own classes:Code: (edl) [Select]
button_set_parent(button, window1);
window_set_parent(window1, window2);
Instead of bazillion variants like this:Code: (edl) [Select]
button_set_parent_window(button, window1);
window_set_parent_window(window1, window2);
So basically I want the ID returned by functions like button_create(), not to be an integer without any type information, but identifiable as an instance of a class.One way to fix this would be to ask users to code in C++. So they could in fact write:
Code: (edl) [Select]
Button button1 = button_create();
And then use "button1" everywhere as it's a C++ class. But I don't want that. I want the user to be able, to write:Code: (edl) [Select]
button1 = button_create();
In my case maybe the third option could work, as I basically would have a GUI_MAP having all the GUI elements which would mean that every one will have a unique ID. But I wouldn't be able to use this for other resources like sprites or backgrounds.
So this topic is mostly addressed to Josh, as he deals with EDL. How would you propose to fix this?
19
General ENIGMA / GL3 lights fixes
« on: June 20, 2014, 07:58:26 am »GL3 light fixes
So I implemented lights in GL3 some time ago, but I didn't do it in Master branch because AMD fails. It worked fine and dandy on Nvidia, but on AMD it didn't render models with lights for some reason. After days of testing I still didn't figure out what the problem is, but I did found a workaround. I send color data to GPU even if they are not used. This reduces FPS slightly (goes from 1170 to 1150 on Nvidia), but now it at least works on AMD. Additional investigation should be done into that matter, but at least we can have lights now.So this is how it looks like on AMD with GL1 and GL3:
You can see that they are not pixel identical, but very close and this is about the difference you might even expect from different card vendors when using FFP (GL1). But at least AMD draws everything now.
Default shader override
The default shader (per-vertex lighting which emulates FFP) is quite bad and basic. That is the idea for now, as we wanted both systems to be compatible. But if you want to make something that actually looks good, then you might have to use your own shaders. This is of course possible, but until now you couldn't override what is actually the "default shader". So your code looked like this:Code: (EDL) [Select]
glsl_program_set(shr_my_cool_effect_shader);
//Draw the cool effect
glsl_program_set(shr_my_default_shader);
//Draw normally with a custom default shader
instead of this:Code: (EDL) [Select]
//Create
glsl_program_default_set(shr_my_default_shader);
//Draw
glsl_program_set(shr_my_cool_effect_shader);
//Draw the cool effect
glsl_program_reset();
//Draw normally with a custom default shader
It is not a big change, but the reason I point this out is because we now could theoretically allow extensions which override this shader automatically. Like imagine a "Per-pixel lighting" extension, you Enable it and it automatically sets the shader. The extension doesn't even need to have functions. Sadly though, extensions still can't modify or inject code into events. So right now it's not possible to do it without a function, but it might be in the future. Like I made an example:Here I switch between shaders with keyboard:
Code: [Select]
if (keyboard_check_pressed(vk_insert)){
glsl_program_default_set(shr_per_pixel);
glsl_program_reset();
}else if (keyboard_check_pressed(vk_delete)){
glsl_program_default_reset();
glsl_program_reset();
}
The glsl_program_reset(); is required because the _default_ functions don't actually bind the program. They just set what the default one is.Faster speed
I can't be sure about AMD as it was broken before, but my Nvidia implementation works a lot faster than before. The current master is actually very broken, I have about 250fps on it. After fixing lights I got it up to 1090FPS (which is what it was before and is with GL1), but I also did additional caching and now get about 1180FPS, so there is an improvement. Others should probably see it too.What I need from you
Please test these changes, by downloading from this branch - https://github.com/enigma-dev/enigma-dev/commits/GL3-cleanupEspecially AMD users should test. Try with Project Mario as well as other examples and games. You can also test this: https://www.dropbox.com/s/r17cwch4962voi8/3D_Lights_test.egm - It's the lights demo where you can see the default FFP emulation and the sample per-pixel lighting. You can switch between them using Delete and Insert, look around with mouse and move with WASD.
It would also be useful to know FPS in examples like Project Mario before (the Master branch) and after (this one).
If everything is okay and nothing else breaks, then the branch could be merged.
20
General ENIGMA / Variable performance
« on: April 29, 2014, 03:16:02 pm »
Found a GM topic here: http://gmc.yoyogames.com/index.php?showtopic=604444
Some users basically tried to measure several different variable read/write performances. So I though I could compare to ENIGMA. Sadly I don't have YYC so I can't test it, and comparing to regular GM wouldn't really be fair. So this is YYC from the topic:
So here is ENIGMA:
It does seems we are faster at few and slower at others. Comparing the two isn't correct though, as the YYC result wasn't done on my PC. But I do believe some of the iterative methods we have now are indeed slower than YYC could have (as theirs could be coded better, as it is few years newer as well). Just for comparison here is what happens when the "var" is replaced by "int" (so when we declare the type):
We can see that all of the ones which previously used "var" and were slow are now A LOT faster. Some went from 3000us to 0us (to it was not even measurable) while others went from 115000us to 7000us (16x speedup).
Many others didn't change because I can't override things like built-in variables to use int. So I changed only the ones having specific "var" declaration. I also changed the string, so you can actually see which ones were changed. So look for the ones having "int" in the name.
So while there are things we should improve engine wise, we still have the ability to define variables that give a massive speedup. And I encourage people to use them.
This topic was created in the "series" of the other topics involving variables.
Some users basically tried to measure several different variable read/write performances. So I though I could compare to ENIGMA. Sadly I don't have YYC so I can't test it, and comparing to regular GM wouldn't really be fair. So this is YYC from the topic:
So here is ENIGMA:
It does seems we are faster at few and slower at others. Comparing the two isn't correct though, as the YYC result wasn't done on my PC. But I do believe some of the iterative methods we have now are indeed slower than YYC could have (as theirs could be coded better, as it is few years newer as well). Just for comparison here is what happens when the "var" is replaced by "int" (so when we declare the type):
We can see that all of the ones which previously used "var" and were slow are now A LOT faster. Some went from 3000us to 0us (to it was not even measurable) while others went from 115000us to 7000us (16x speedup).
Many others didn't change because I can't override things like built-in variables to use int. So I changed only the ones having specific "var" declaration. I also changed the string, so you can actually see which ones were changed. So look for the ones having "int" in the name.
So while there are things we should improve engine wise, we still have the ability to define variables that give a massive speedup. And I encourage people to use them.
This topic was created in the "series" of the other topics involving variables.
21
General ENIGMA / The new GL3
« on: February 06, 2014, 07:57:04 pm »
Hi! Wanted to give some progress on my efforts of ridding GL3 from deprecated functions. As many of you might already know, the GL3 version was still mostly FFP (fixed-function pipeline). This means four things:
1) It doesn't use the newest GL and hardware capabilities.
2) It makes using newest GL capabilities a pain (like writing shaders in the GL1.1 is a pain).
3) It's not actually GL3 - even though we call it that.
4) And probably most importantly - It makes ports harder. GLES 2.0 is a subset of GL3. This means that a fully working GL3 without deprecated functions allow A LOT easier porting to embedded devices like Android phones.
Note: In this topic I will say GL3 everywhere, when in fact it's GL3.1 full context or even GL3.2 core (but no GL3.2 functions are used).
So what I did was first write a matrix library to replace the GL matrix madness, as GL3 actually doesn't support GL matrices anymore. It all has to be done by the developer.
Performance changes for GL1.1 were these:
So in Minecraft example which doesn't use that many transform functions, there was no difference. No gain or loss. But in Project Mario there was 90FPS increase which is about 9%. In games that use A LOT of transform functions improvements will be greater. So the worst case is no difference, best case is improvement. And as this doesn't create any compatibility issues, then I don't see why free performance gain should be discarded. Plus, this allows gaining even more performance when specific improvements to matrix code is done (like using MMX/SSE instructions on PC's).
Here the OLD is the one currently in GIT MASTER. The V1 is the version where only matrices are changed. It uses basically the same code as GL1.1, but the only difference is that matrix multiplication and sending to GL (via glLoadMatrix) is done not during the _transform_ call, but during render call (but only if update was needed). This means that examples like minecraft got a 70FPS boost without problem, as it has relatively few render calls. Project Mario on the other hand has a lot more (my debugger even shows Mario tries to render vertex buffers with only 1 vertex, which Robert and I should investigate), so there the FPS was massively decreased.
In V2 I finally removed FPP and added shaders. This meant that FPS was mostly increased, but the method was still sub-optimal (I queried uniform and attribute locations every draw call which of course is stupid). To be honest, I cannot remember why Minecraft had 265FPS reduction in this one.
And V3 is the current one. Locations for shaders are loaded when linking the shader program, fixed problems with texture coordinates being passed to shaders, while there is in fact no textures and so on (like when drawing d3d_model_block with texture == -1). This shows an overall improvement and so I finally got it working at least as fast and even faster than the older implementation.
But this is not the end - It will still go both ways. The shaders I wrote are quite primitive and don't have things like lights or fog. This means that when those are implemented, then the speed might decrease. On the other hand there are more optimizations to be done, like maybe using vertex array objects (VAO).
1) The shaders shouldn't be that complicated even after all these FPP things have been implemented, as FFP didn't support things like normal mapping or any other more advanced thing.
2) This will be a lot easier and shorter. Writing all of the possible shaders by hand will be madness, even when the rendering possibilities are limited, and I don't plan to write a shader generator.
3) Performance impact could be negligible, but I cannot be sure. The slowest things in shaders are branches - if/else statements. If the if statement depends on the fragment (like you do "if (v_TextureCoord.t) == 0)") then performance can be severely impacted (like I saw an example where a basic change like that took 60FPS down to 20FPS in an IOS device). This happens because then shader units don't work in parallel in this case. Nvidia, for example, uses something called Warps - they are basically batches that work on several pixels at once - like 32. If all of them have the same instructions (so branching doesn't change per pixel), then they work very fast. If even one of the pixels in the warp branches differently, then performance impact is significant. The reason I write it here is because "ubershader" will require branches, but the speed shouldn't be impacted because they will use uniform constants. Like if we don't use coloring, then all of the pixels in the drawing call will not use coloring. This is currently the basic default fragment shader:
So, any suggestions and ideas? There wasn't much of a point to this topic, but I just wanted to share with things that might come in future. Merging my fork will probably be a pain, as I am like 50 commits behind Master, but conflicts should be minimal. This will not be merged until I replicate also lighting and do more tests. Then I would want others to try as well (other hardware and OS's). These changes will probably break GL3 to some people here (like Poly), but that is because their hardware just don't support GL3 in the first place. They currently can run it, because the implementation in Master is more like GL2.
1) It doesn't use the newest GL and hardware capabilities.
2) It makes using newest GL capabilities a pain (like writing shaders in the GL1.1 is a pain).
3) It's not actually GL3 - even though we call it that.
4) And probably most importantly - It makes ports harder. GLES 2.0 is a subset of GL3. This means that a fully working GL3 without deprecated functions allow A LOT easier porting to embedded devices like Android phones.
Note: In this topic I will say GL3 everywhere, when in fact it's GL3.1 full context or even GL3.2 core (but no GL3.2 functions are used).
So what I did was first write a matrix library to replace the GL matrix madness, as GL3 actually doesn't support GL matrices anymore. It all has to be done by the developer.
Performance
GL1.1
While I was at it, I noticed that these changes also help GL1.1, as there were many useless functions in _transform_ that only slowed it down, but were necessary for the old GL way of doing things. In GL1.1 - matrices are used only in transformation functions and so the speed differences are based on how many d3d_transform_ functions are used. For all comparison I used two 3D examples which used a lot of 3D functionality - Minecraft example and the Project Mario game. The FPS are average after convergence in the game (so in both examples I don't move at all - after the game starts I wait until they both hit a steady point, like Mario going to sleep in Project Mario).Performance changes for GL1.1 were these:
So in Minecraft example which doesn't use that many transform functions, there was no difference. No gain or loss. But in Project Mario there was 90FPS increase which is about 9%. In games that use A LOT of transform functions improvements will be greater. So the worst case is no difference, best case is improvement. And as this doesn't create any compatibility issues, then I don't see why free performance gain should be discarded. Plus, this allows gaining even more performance when specific improvements to matrix code is done (like using MMX/SSE instructions on PC's).
GL3
For GL3 I will show also the progress by iterations (or GIT commits if you will) and tell what went wrong and what went right.Here the OLD is the one currently in GIT MASTER. The V1 is the version where only matrices are changed. It uses basically the same code as GL1.1, but the only difference is that matrix multiplication and sending to GL (via glLoadMatrix) is done not during the _transform_ call, but during render call (but only if update was needed). This means that examples like minecraft got a 70FPS boost without problem, as it has relatively few render calls. Project Mario on the other hand has a lot more (my debugger even shows Mario tries to render vertex buffers with only 1 vertex, which Robert and I should investigate), so there the FPS was massively decreased.
In V2 I finally removed FPP and added shaders. This meant that FPS was mostly increased, but the method was still sub-optimal (I queried uniform and attribute locations every draw call which of course is stupid). To be honest, I cannot remember why Minecraft had 265FPS reduction in this one.
And V3 is the current one. Locations for shaders are loaded when linking the shader program, fixed problems with texture coordinates being passed to shaders, while there is in fact no textures and so on (like when drawing d3d_model_block with texture == -1). This shows an overall improvement and so I finally got it working at least as fast and even faster than the older implementation.
But this is not the end - It will still go both ways. The shaders I wrote are quite primitive and don't have things like lights or fog. This means that when those are implemented, then the speed might decrease. On the other hand there are more optimizations to be done, like maybe using vertex array objects (VAO).
Shaders
Prefixes
I chose to go with the method done in ThreeJS and make prefixes for both fragment and vertex shaders. This means that when a user in ENIGMA codes a shader, there will be a prefix appended to the top of his code. This prefix defines things like matrices (projectionMatrix, viewMatrix, modelViewProjectionMatrix etc. as well as gm_Matrices[] for compatibility with GM:S), default attributes (vertex positions, texture positions, vertex colors and so on) and uniforms (like whether texture is bound or to get bound color (works like draw_get_color() in shader)). This makes writing shaders a lot easier as most of the needed stuff is already there. Shader compilers remove unused uniforms and attributes, so if the user writes a shader that doesn't use these functions (like a user doesn't need vertex color for example), then the shader will optimize out the color attribute. That is why these prefixes are so good - they don't have any real penalty. In the end the prefix's could get quite large and we also need to check what GM:S appends as well to make it compatible, but I don't think they are going to make a difference performance wise. They are mostly #define's and things like that.Default shader
The default shader (bound by default on startup or when calling glsl_program_reset()) will have to replicate all the FPP stuff ENIGMA and GM allowed to use. This include flat and smooth shading for lights (up to 8 lights if I am not mistaken), fog (colored and with different falloff functions) and a few other things. The best way (or the "proper" way) to do this is to make several shaders - one with lights enabled, one with disabled, one with texturing, one without and so on. The combinations are going to be large though and so we either have to make our own shader generator (quite often done actually) or just make an "ubershader". And "ubershader" is something that does all of these things and you control everything via uniforms. I personally think that we might as well do it this way because of three reason:1) The shaders shouldn't be that complicated even after all these FPP things have been implemented, as FFP didn't support things like normal mapping or any other more advanced thing.
2) This will be a lot easier and shorter. Writing all of the possible shaders by hand will be madness, even when the rendering possibilities are limited, and I don't plan to write a shader generator.
3) Performance impact could be negligible, but I cannot be sure. The slowest things in shaders are branches - if/else statements. If the if statement depends on the fragment (like you do "if (v_TextureCoord.t) == 0)") then performance can be severely impacted (like I saw an example where a basic change like that took 60FPS down to 20FPS in an IOS device). This happens because then shader units don't work in parallel in this case. Nvidia, for example, uses something called Warps - they are basically batches that work on several pixels at once - like 32. If all of them have the same instructions (so branching doesn't change per pixel), then they work very fast. If even one of the pixels in the warp branches differently, then performance impact is significant. The reason I write it here is because "ubershader" will require branches, but the speed shouldn't be impacted because they will use uniform constants. Like if we don't use coloring, then all of the pixels in the drawing call will not use coloring. This is currently the basic default fragment shader:
Code: [Select]
in vec2 v_TextureCoord;
in vec4 v_Color;
out vec4 out_FragColor;
void main()
{
if (en_Texturing == true && en_Color == true){
out_FragColor = texture2D( TexSampler, v_TextureCoord.st ) * v_Color;
}else if (en_Color == true){
out_FragColor = v_Color;
}else if (en_Texturing == true){
out_FragColor = texture2D( TexSampler, v_TextureCoord.st );
}else{
out_FragColor = en_bound_color;
}
}
Here you can see that the branching is static. And on my 660Ti this branching doesn't decrease FPS at all (when I remove branching I get exactly the same FPS). I read a theory (without technical evidence though) that maybe shader compilers make several shaders - one for every static branch. This means if I pass en_Color == true and en_Texturing == false, then it won't even consider the first branch. It does seem that my GPU might do this, but I am not sure. Coloring
There have been like 3 or 4 topics about this already in this forum and no real consensus whether we should blend with bound color or not. In the shader above you can see that the current method replicates GL1.1 implementation. So if texture is used and a per vertex color is used, then we blend the texture and the color. If only color is used (like when using draw_rectangle_color) then only vertex color is used. When drawing with texture, then only texture is used (so "draw_set_color(c_red); draw_model(model,texture);" will NOT draw a red tinted model). And when no per vertex color or texture is bound, then it uses the bound color. So "draw_set_color(c_red); draw_set_alpha(.5); d3d_draw_block(..., texture = -1, ..);" will draw a transparent red block.Deprecated functions
All these changes we mostly done with one idea - to remove all deprecated functions. Right now these two examples run with without calling any deprecated functions per frame. There are still some deprecated GL functions here and there (like inside d3d_start() and d3d_end()), but I will remove them soon enough.So, any suggestions and ideas? There wasn't much of a point to this topic, but I just wanted to share with things that might come in future. Merging my fork will probably be a pain, as I am like 50 commits behind Master, but conflicts should be minimal. This will not be merged until I replicate also lighting and do more tests. Then I would want others to try as well (other hardware and OS's). These changes will probably break GL3 to some people here (like Poly), but that is because their hardware just don't support GL3 in the first place. They currently can run it, because the implementation in Master is more like GL2.
22
Issues Help Desk / Merging unfinished changes
« on: December 09, 2013, 07:18:19 am »
It seems that all the changes now being made to object system and whatnot have broken ENIGMA. While it's something that usually happens, I don't think we should keep doing that. The guy making the changes could of just finished the whole thing and then it could be merged. Same with many other pull requests.
Although it's possible my current problem is not connected to these particular changes, but who knows. Right now I can compile fine, but the exe is empty (white windows) even when I add a room (blue background by default) and objects. Someone can replicate this?
But this bug aside, we should merge only when functional. That is why I am still waiting for those integration tests from fortevin.
Although it's possible my current problem is not connected to these particular changes, but who knows. Right now I can compile fine, but the exe is empty (white windows) even when I add a room (blue background by default) and objects. Someone can replicate this?
But this bug aside, we should merge only when functional. That is why I am still waiting for those integration tests from fortevin.
23
Issues Help Desk / ENIGMA exe bloat
« on: November 12, 2013, 03:53:29 pm »
ENIGMA's exported games hasn't been very small for a while now. But I noticed that since last few commits (in the last month or so I guess) an empty game (one empty room) with all extensions disabled and Audio-None, Widgets-None, Collision-None and GL-1.1 - I get 6.4mb. About a month ago it was about 3.4mb. So somebody really bloated the thing. I think we should take a look why it is like that. We should probably get it a lot smaller than 3.4mb as well.
GL1.1 - 6.4mb
DX9 - 5.8mb
GL3 - 6.4mb
GL1.1 - 6.4mb
DX9 - 5.8mb
GL3 - 6.4mb
24
General ENIGMA / GL3 matrices
« on: October 18, 2013, 03:02:24 pm »
What would be the best matrix library to use for GL3 matrices (view matrix, model matrix and so on)? I see that there is glm.g-truc.net, but it's 1.6mb. Then there is VS*L http://www.lighthouse3d.com/very-simple-libs/vsml/ and it is smaller, but I think it has a lot more dependencies. GLM is a header only library on the other hand, so it is easier to include. Any other ideas? Technically we can write our own (have done this) or just use the code included here: http://www.lighthouse3d.com/cg-topics/code-samples/opengl-3-3-glsl-1-5-sample/ . Graphics really don't need all the fancy matrix math. It needs addition, multiplication and inversion and all of those functions can be optimized, because graphics only use 4x4 matrices.
This is a topic I actually mentioned earlier (when I actually wanted to remove all deprecated stuff from GL3). Now the idea is back and we need to start with a decision.
edit: Also found CML, http://cmldev.net/. Also seems to be include only, ~690kb.
This is a topic I actually mentioned earlier (when I actually wanted to remove all deprecated stuff from GL3). Now the idea is back and we need to start with a decision.
edit: Also found CML, http://cmldev.net/. Also seems to be include only, ~690kb.
25
Issues Help Desk / Parenting and even inheritance
« on: August 29, 2013, 02:23:14 pm »
This are two things the new parser should fix right? Josh, how is it going?
A user asked me to convert this example for him: http://gmc.yoyogames.com/index.php?showtopic=456948
And besides things like variable_exists(), it uses a lot of parenting and inheritance (even the event_inherited(); function). And as many use them I just wanted to know how is that going?
I will probably rewrite the example to not use parenting, but that just involves a lot of code duplication.
edit: The parser also seems to fail a lot like this case:
edit2: Also, GM seems to allow break; outside a loop or a switch which makes it work like "exit": http://wiki.yoyogames.com/index.php/Break. ENIGMA doesn't allow that. Not sure we even should allow that... but you know.. compatibility.
A user asked me to convert this example for him: http://gmc.yoyogames.com/index.php?showtopic=456948
And besides things like variable_exists(), it uses a lot of parenting and inheritance (even the event_inherited(); function). And as many use them I just wanted to know how is that going?
I will probably rewrite the example to not use parenting, but that just involves a lot of code duplication.
edit: The parser also seems to fail a lot like this case:
Code: [Select]
var near=instance_nearest(x,y,obj_Player_Camara_Parent);
outputs as this:Code: [Select]
var = instance_nearest(x, y, obj_Player_Camara_Parent);
And Code: [Select]
var near; near=instance_nearest(x,y,obj_Player_Camara_Parent);
Error in the syntax checker with "Primary expression expected before operator". But it seems to be a variable issue, because when I rename "near" into "tid" or something else, then it works. Is "near" used specifically somewhere in the parser or the compiler? I see these problems with variable names a lot. I think other than type names (int, short, double etc.) all other should be available. Especially if it is not shown in the code editor (type names are bold for example, while "near" is just normal). So we should find all these variables and define them in a way that doesn't make the conflict.edit2: Also, GM seems to allow break; outside a loop or a switch which makes it work like "exit": http://wiki.yoyogames.com/index.php/Break. ENIGMA doesn't allow that. Not sure we even should allow that... but you know.. compatibility.
26
General ENIGMA / Compiling from source
« on: August 23, 2013, 04:02:47 pm »
All the changes to support installations have it made very hard to make it work from source on Windows. What I want to do:
1) Clone git (via GIT or just download master from github) and extract to folder C:/enigma-dev.
2) Compile compileEGMf.dll via the C::B project. It still doesn't work flawlessly as the textfile.cpp needs to removed from it (as it doesn't exist) and the paths need to be changed (right now it's in some documents), but after these changes it works. So I now have compiled compileEGMf.dll.
3) Compile ENIGMA.exe via C::B project (or makefile, whatever). This can be done via the stupidity-buffer (should rename that as I don't know what exactly it is referring to) and then I get ENIGMA.exe.
4) Extract newest LGM with ENIGMA plugin and put it in C:/enigma-dev.
5) Extract /additional needed (should be a separate downloadable .zip without LGM or anything else added).
The problem now is that ENIGMA.exe is modified so it requires some "init" and "compiled" and such files. I copied the files from installer as they are not available elsewhere, but it still doesn't work because it thinks enigma-dev should be a subdirectory. After I do that it tries to compile the .dll and the .exe again even though I already did that. It fails, because it tries to use mingw32 that comes with the installer (I think) so it uses some bizarre path to mingw that doesn't exist (which I think it gets from gcc.ey).
To fix this I need to change the "make: mingw32-make.exe" to "make: C:/mingw/bin/mingw32-make.exe" inside the gcc.ey. After that it still tries to compile the .dll, but it cannot and errors out with this:
So thoughts:
1) Allow ENIGMA.exe to run without all those files and with LGM being in the same directory as the .exe. This way it will just run LGM and won't make it update/compile everything + I won't have to use the installer just to get those files.
2) If the .dll is present, then don't make it compile it again. So to upgrade you would delete it, but if it is compiled another way (or just copied from another source), then it can be used without recompilation, as I clearly cannot do it via the plugin (the error above).
3) Put the windows/gcc.ey in git. I think previously it was generated and so it was even recommended to delete it. Right now it is not generated and LGM plugin fails if it is not found. So I again had to use the installer to get it. And I had to modify it to have the make: path just because it can't find mingw32-make.exe while it is in PATH (I can do cmd->mingw32-make.exe just fine, so it is weird that LGM cannot find it).
So in essence I cannot install ENIGMA on my desktop PC right now. That is why I haven't developed anything and why I cannot help another user (AsherOS) with his problems. So any ideas/suggestions? I think the 3 points I added should be done and if anyone can do it (I don't think it's hard, just some if checks mostly), then it would be great.
1) Clone git (via GIT or just download master from github) and extract to folder C:/enigma-dev.
2) Compile compileEGMf.dll via the C::B project. It still doesn't work flawlessly as the textfile.cpp needs to removed from it (as it doesn't exist) and the paths need to be changed (right now it's in some documents), but after these changes it works. So I now have compiled compileEGMf.dll.
3) Compile ENIGMA.exe via C::B project (or makefile, whatever). This can be done via the stupidity-buffer (should rename that as I don't know what exactly it is referring to) and then I get ENIGMA.exe.
4) Extract newest LGM with ENIGMA plugin and put it in C:/enigma-dev.
5) Extract /additional needed (should be a separate downloadable .zip without LGM or anything else added).
The problem now is that ENIGMA.exe is modified so it requires some "init" and "compiled" and such files. I copied the files from installer as they are not available elsewhere, but it still doesn't work because it thinks enigma-dev should be a subdirectory. After I do that it tries to compile the .dll and the .exe again even though I already did that. It fails, because it tries to use mingw32 that comes with the installer (I think) so it uses some bizarre path to mingw that doesn't exist (which I think it gets from gcc.ey).
To fix this I need to change the "make: mingw32-make.exe" to "make: C:/mingw/bin/mingw32-make.exe" inside the gcc.ey. After that it still tries to compile the .dll, but it cannot and errors out with this:
Quote
Java Version: 10700 (1.7.0_25)
Loading lib files in E:\enigma-dev\enigma-dev\lateralgm.jar
01_move.lgl 02_main1.lgl 03_main2.lgl 04_control.lgl
05_score.lgl 06_extra.lgl 07_draw.lgl
Calling `C:/mingw/bin/mingw32-make.exe eTCpath="null"`
> C:/mingw/bin/mingw32-make -j 3 -C CompilerSource
> Access denied - .
> File not found - -NAME
> File not found - -AND
> File not found - !
> File not found - -NAME
> mingw32-make[1]: Entering directory `E:/enigma-dev/enigma-dev/CompilerSource'
> process_begin: CreateProcess(NULL, uname -s, ...) failed.
> mingw32-make[1]: Leaving directory `E:/enigma-dev/enigma-dev/CompilerSource'
> mingw32-make[1]: *** No rule to make target `.eobjs/----------', needed by `../compileEGMf.dll'. Stop.
> mingw32-make: *** [ENIGMA] Error 2
2
Process terminated
So thoughts:
1) Allow ENIGMA.exe to run without all those files and with LGM being in the same directory as the .exe. This way it will just run LGM and won't make it update/compile everything + I won't have to use the installer just to get those files.
2) If the .dll is present, then don't make it compile it again. So to upgrade you would delete it, but if it is compiled another way (or just copied from another source), then it can be used without recompilation, as I clearly cannot do it via the plugin (the error above).
3) Put the windows/gcc.ey in git. I think previously it was generated and so it was even recommended to delete it. Right now it is not generated and LGM plugin fails if it is not found. So I again had to use the installer to get it. And I had to modify it to have the make: path just because it can't find mingw32-make.exe while it is in PATH (I can do cmd->mingw32-make.exe just fine, so it is weird that LGM cannot find it).
So in essence I cannot install ENIGMA on my desktop PC right now. That is why I haven't developed anything and why I cannot help another user (AsherOS) with his problems. So any ideas/suggestions? I think the 3 points I added should be done and if anyone can do it (I don't think it's hard, just some if checks mostly), then it would be great.
27
Proposals / GL3 changes from immediate to retained mode
« on: July 30, 2013, 11:44:34 am »
Hi! I think I made a topic about this a long time ago, but lets do it again. We have GL3 for some time now, but most of the things are still rendered in immediate mode. So I propose changing all the drawing functions not to use it. The problem is with caching, if we even decide use it. Right now we render a sprite like so:
So basically what I propose is this:
1) Have 1 global VBO.
2) In all drawing functions we populate this FBO with x,y,tx,ty,r,g,b,a and do that until texture_use() fails (eg, when the currently used texture is not the same as the requested one) at which point we draw the VBO and clear it.
3) Bind the new texture and repeat.
Advantages:
1) This way we will batch as much as we can before drawing and yet have the possibility to use different drawing functions (even sprite and background) interchangeably.
2) When we add sprite packing (or more precisely texture packing), then we will have a massive speed boost without changing any drawing functions. This is because we push the texture coordinates and render only when texture changes. So less texture changes means more batching.
3) Tiles would automatically be batched (usually), because calling draw_background_ext_transformed like previously would automatically make them be added to the same VBO (if the same tilestrip is used which often is). Right now it seems some GLLists are made and populated, by I think that is slower (especially when many glBegin and glEnd functions are used per tile). Of course remaking the tile system for 1 VBO per layer could maybe be better and speed the whole thing up (but will take more memory).
4) Port to GLES (Android and such) would be a lot simpler, as it doesn't support immediate mode and requires the app to basically be GL3 (so no gl transformation functions either). So we must push towards that for easier maintenance and compatibility.
Disadvantages:
1) If a lot of texture switching happens (like having two objects with the same depth and be created interleaved with one another, so the draw event is called interleaved as well)) then there will be a performance impact. On a game with few hundred sprites it will probably not be seen, but with thousands of sprites the impact could be noticeable. The good thing is that things like depth changes would reduce the impact. As well as texture packing.
note: Functions like glEnableClientState and such are actually also deprecated. Now all of that has to happen on a vertex shader. I plan to test that too and maybe implement it that way. But this global VBO thing is a lot simpler and could potentially give a lot of speed.
So, any ideas?
edit: By replacing glBufferData with glBufferSubData I got to 36FPS with 100k objects, but this won't be possible in the implementation mentioned here (as the size will change all the time depending on how many sprites are drawn and how many texture swaps happen). But with a much smaller VBO the impact of that function will not be so great. It is even recommended to use several smaller VBO's than one big one anyway.
Code: [Select]
void draw_sprite(int spr, int subimg, gs_scalar x, gs_scalar y)
{
get_spritev(spr2d,spr);
const int usi = subimg >= 0 ? (subimg % spr2d->subcount) : int(((enigma::object_graphics*)enigma::instance_event_iterator->inst)->image_index) % spr2d->subcount;
texture_use(GmTextures[spr2d->texturearray[usi]]->gltex);
glPushAttrib(GL_CURRENT_BIT);
glColor4f(1,1,1,1);
const float tbx = spr2d->texbordxarray[usi], tby = spr2d->texbordyarray[usi],
xvert1 = x-spr2d->xoffset, xvert2 = xvert1 + spr2d->width,
yvert1 = y-spr2d->yoffset, yvert2 = yvert1 + spr2d->height;
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex2f(xvert1,yvert1);
glTexCoord2f(tbx,0);
glVertex2f(xvert2,yvert1);
glTexCoord2f(tbx,tby);
glVertex2f(xvert2,yvert2);
glTexCoord2f(0,tby);
glVertex2f(xvert1,yvert2);
glEnd();
glPopAttrib();
}
This means in immediate mode it sends vertices one by one and is bad and slow and deprecated. The change would be using VAO's or VBO's which are sadly for more static geometry. It requires rebuilding the buffer all the time before drawing. So if just do this:Code: [Select]
void draw_sprite(int spr, int subimg, gs_scalar x, gs_scalar y)
{
get_spritev(spr2d,spr);
const int usi = subimg >= 0 ? (subimg % spr2d->subcount) : int(((enigma::object_graphics*)enigma::instance_event_iterator->inst)->image_index) % spr2d->subcount;
texture_use(GmTextures[spr2d->texturearray[usi]]->gltex);
const float tbx = spr2d->texbordxarray[usi], tby = spr2d->texbordyarray[usi],
xvert1 = x-spr2d->xoffset, xvert2 = xvert1 + spr2d->width,
yvert1 = y-spr2d->yoffset, yvert2 = yvert1 + spr2d->height;
float data[][7] = {
{ xvert1, yvert1, 0.0, 0.0, 1.0, 1.0, 1.0 },
{ xvert2, yvert1, tbx, 0.0, 1.0, 1.0, 1.0 },
{ xvert2, yvert2, tbx, tby, 1.0, 1.0, 1.0 },
{ xvert2, yvert2, tbx, tby, 1.0, 1.0, 1.0 },
{ xvert1, yvert2, 0.0, tby, 1.0, 1.0, 1.0 },
{ xvert1, yvert1, 0.0, 0.0, 1.0, 1.0, 1.0 }
};
GLuint spriteVBO;
glGenBuffers(1, &spriteVBO);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, spriteVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
glVertexPointer( 2, GL_FLOAT, sizeof(float) * 7, NULL );
glTexCoordPointer( 2, GL_FLOAT, sizeof(float) * 7, (void*)(sizeof(float) * 2) );
glColorPointer( 3, GL_FLOAT, sizeof(float) * 7, (void*)(sizeof(float) * 4) );
glDrawArrays( GL_TRIANGLES, 0, 6);
glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );
glDeleteBuffers(1, &spriteVBO);
}
Then we will be using VBO's, but because we rebuild both the VBO and the data, then it ends up A LOT slower. So does anyone have any ideas on how we could buffer this? Originally I thought if it could be possible to assign some ID for each draw call which could be used throughout frames? So it could be possible to draw the same sprite if no such things like sprite index or position has changed? Or that even if we could create 1 VBO per sprite and then just rebuild the data per render, then it would be a lot faster? But I just did some tests and even if I only call:Code: [Select]
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
glDrawArrays( GL_TRIANGLES, 0, 6);
Then it is still a lot slower then immediate mode. The problem I guess is that we need to batch sprites into one VBO. But it cannot be painlessly done with all the dynamic things we have. I tried a quick hack by using a global vbo and then populating it in draw_sprite() just before drawing and I got a 3 times boost over immediate mode (though I seemed to get capped at exactly 100-101FPS, which mean it maybe was more, but for some reason I got vsyn'ced). That means I drawn 25k objects together with their logic (simple "bounce against walls" logic) and I got 30FPS with immediate mode and 100FPS with global VBO. 100k objects were 9fps for immediate and stable 25FPS with VBO. But I tested without drawing and found that I was actually capped at 33FPS by my use of a vector (I pushed 6*7 values for each sprite and there were 100k of them). Dunno how to improve that much though. After reserving and using manual counter (so no need for clear, just overwrite) I got to 44FPS (which was 30FPS with drawing).So basically what I propose is this:
1) Have 1 global VBO.
2) In all drawing functions we populate this FBO with x,y,tx,ty,r,g,b,a and do that until texture_use() fails (eg, when the currently used texture is not the same as the requested one) at which point we draw the VBO and clear it.
3) Bind the new texture and repeat.
Advantages:
1) This way we will batch as much as we can before drawing and yet have the possibility to use different drawing functions (even sprite and background) interchangeably.
2) When we add sprite packing (or more precisely texture packing), then we will have a massive speed boost without changing any drawing functions. This is because we push the texture coordinates and render only when texture changes. So less texture changes means more batching.
3) Tiles would automatically be batched (usually), because calling draw_background_ext_transformed like previously would automatically make them be added to the same VBO (if the same tilestrip is used which often is). Right now it seems some GLLists are made and populated, by I think that is slower (especially when many glBegin and glEnd functions are used per tile). Of course remaking the tile system for 1 VBO per layer could maybe be better and speed the whole thing up (but will take more memory).
4) Port to GLES (Android and such) would be a lot simpler, as it doesn't support immediate mode and requires the app to basically be GL3 (so no gl transformation functions either). So we must push towards that for easier maintenance and compatibility.
Disadvantages:
1) If a lot of texture switching happens (like having two objects with the same depth and be created interleaved with one another, so the draw event is called interleaved as well)) then there will be a performance impact. On a game with few hundred sprites it will probably not be seen, but with thousands of sprites the impact could be noticeable. The good thing is that things like depth changes would reduce the impact. As well as texture packing.
note: Functions like glEnableClientState and such are actually also deprecated. Now all of that has to happen on a vertex shader. I plan to test that too and maybe implement it that way. But this global VBO thing is a lot simpler and could potentially give a lot of speed.
So, any ideas?
edit: By replacing glBufferData with glBufferSubData I got to 36FPS with 100k objects, but this won't be possible in the implementation mentioned here (as the size will change all the time depending on how many sprites are drawn and how many texture swaps happen). But with a much smaller VBO the impact of that function will not be so great. It is even recommended to use several smaller VBO's than one big one anyway.
28
Proposals / Vertex color
« on: July 28, 2013, 08:25:05 am »
Hi. I just noticed that vertex color was not implemented. This effectively broke many model functions and all primitive functions. I then implemented color buffer, but what do we do about these cases:
draw_vertex() - I made it use bound color and alpha.I think that was how GM did it, but now I am not sure. Will check when I have the chance. Confirmed, this is how it's done in GM.
d3d_model_vertex() - Should this also use bound color and alpha? Problem is that default bound color is black. As examples in EDC which run in GM doesn't set any color to white before adding the vertexes, then I belive it doesn't use bound color and alpha and just uses c_white and 1.
1) So should we use bound color and alpha or just set everything to c_white and 1?
2) Should we just not bind color buffer at all if color is not used? It didn't seem to work in draw_primitive() case, but it works in d3d_model case. I made a bool which turns to 1 when color function is used. Otherwise it's 0. Question is also if its faster. We do use less memory and I guess model building is faster as it doesn't send useless data to GPU. So maybe this bool method is better than filling vector with c_white and 1.0 all the time (which is extra 4 gs_scalar's for every vertex).
edit: I just tested and here are some clarifications:
1) GM uses bound color whenever no color is specified. So draw_vertex(), d3d_vertex(), d3d_model_vertex_texture() and so on just use bound color. It never defaults to 1 or c_white.
2) It uses this color when drawing, not when the vertex is added. So when d3d_model_vertex_color() is used, then it bounds color to that vertex at that point. But if d3d_model_vertex() is used, then it defaults to the set color when d3d_model_draw() is used. We cannot really replicate this behavior if we use VBO, as it would require us to loop vertexes and such. We could maybe use glTexEnvf to achieve this, but it would work on all vertexes and not only the changed ones.
I made changes to replicate the 1. part, but it will break the bool fix that I added now and it would break some compatibility. Like the cel shading example at EDC wouldn't work (as all the models would default to black) and it would have to be modified.
edit2: I can also actually make it work for 2) by using the bool fix differently, but then it would break in another case when vertex functions are used interchangeably like this:
If I fix this by making d3d_model_vertex add bound color and alpha, then it wouldn't be buggy, but it would draw differently. The code would draw a black solid triangle with one green corner. The bound color and alpha wouldn't change anything at the point d3d_model_draw is called.
I can fix this by using useColorBuffer bool. So make it add bound color and alpha if d3d_model_vertex is used, but don't bind it to VBO if only d3d_model_vertex's are called and no color functions. This would make examples on EDC work (as they only use d3d_model_vertex or d3d_model_vertex_color and not both together), but it wouldn't work like GM in cases where they are both used together.
draw_vertex() - I made it use bound color and alpha.
d3d_model_vertex() - Should this also use bound color and alpha? Problem is that default bound color is black. As examples in EDC which run in GM doesn't set any color to white before adding the vertexes, then I belive it doesn't use bound color and alpha and just uses c_white and 1.
1) So should we use bound color and alpha or just set everything to c_white and 1?
2) Should we just not bind color buffer at all if color is not used? It didn't seem to work in draw_primitive() case, but it works in d3d_model case. I made a bool which turns to 1 when color function is used. Otherwise it's 0. Question is also if its faster. We do use less memory and I guess model building is faster as it doesn't send useless data to GPU. So maybe this bool method is better than filling vector with c_white and 1.0 all the time (which is extra 4 gs_scalar's for every vertex).
edit: I just tested and here are some clarifications:
1) GM uses bound color whenever no color is specified. So draw_vertex(), d3d_vertex(), d3d_model_vertex_texture() and so on just use bound color. It never defaults to 1 or c_white.
2) It uses this color when drawing, not when the vertex is added. So when d3d_model_vertex_color() is used, then it bounds color to that vertex at that point. But if d3d_model_vertex() is used, then it defaults to the set color when d3d_model_draw() is used. We cannot really replicate this behavior if we use VBO, as it would require us to loop vertexes and such. We could maybe use glTexEnvf to achieve this, but it would work on all vertexes and not only the changed ones.
I made changes to replicate the 1. part, but it will break the bool fix that I added now and it would break some compatibility. Like the cel shading example at EDC wouldn't work (as all the models would default to black) and it would have to be modified.
edit2: I can also actually make it work for 2) by using the bool fix differently, but then it would break in another case when vertex functions are used interchangeably like this:
Code: [Select]
draw_set_color(c_red);
draw_set_alpha(0.5);
draw_primitive_begin(pr_trianglelist);
draw_vertex(10,10);
draw_vertex_color(100,10,c_green,1);
draw_vertex(100,100);
draw_primitive_end();
In GM this would draw a red transparent triangle with one solid green corner. In ENIGMA it would do the same, because the model is rebuilt all the time. But if d3d_model's are used like this:Code: [Select]
//Create
model = d3d_model_create();
d3d_model_primitive_begin(model,pr_trianglelist);
d3d_model_vertex(10,10,0);
d3d_model_vertex_color(100,10,0,c_green,1);
d3d_model_vertex(100,100,0);
d3d_model_primitive_end(model);
//Draw
draw_set_color(c_red);
draw_set_alpha(0.5);
d3d_model_draw(model,0,0,0,-1);
In GM this draws the same as the previous code. In ENIGMA this would break right now. It would break because d3d_model_vertex wouldn't add anything to color vector (and useColorBuffer would be false), but d3d_model_vertex_color would add the color and alpha to the color vector and would set useColorBuffer to true. That means the d3d_model_draw() would bind the color buffer and would think it has 3*4 floats in it (RGBA for every vertex), while in reallity there would be just 1*4.If I fix this by making d3d_model_vertex add bound color and alpha, then it wouldn't be buggy, but it would draw differently. The code would draw a black solid triangle with one green corner. The bound color and alpha wouldn't change anything at the point d3d_model_draw is called.
I can fix this by using useColorBuffer bool. So make it add bound color and alpha if d3d_model_vertex is used, but don't bind it to VBO if only d3d_model_vertex's are called and no color functions. This would make examples on EDC work (as they only use d3d_model_vertex or d3d_model_vertex_color and not both together), but it wouldn't work like GM in cases where they are both used together.
29
Teamwork / Remakes or original content
« on: July 15, 2013, 11:46:00 am »
Hi. I don't have the time or creativity required for original content so I though we (or just I, but some sprite work would be nice) could make some remakes just to show ENIGMA's potential. I would also want the development time to be recorded as rapid game creation I think is the biggest selling point of ENIGMA (if there ever was such a point). The idea came from watching Greenlight and Kickstarter where there are a lot of old style games, but by reading the info it always seems there was a lot of time invested in the coding part. For example, for the past week or so I was hooked on FTL: Faster Than Light and the guys who made it said they did the engine part for 6 months.... and I can assure you that I could remake that engine in maybe a week of intensive work in ENIGMA. The same with Broforce which I saw yesterday. They made it a lot faster (because it originally was for ludum dare), but I believe that in ENIGMA all of that could be made faster still. Same for games like Meatboy and others.
So what you guys think? If anyone has a game they would like me to try to remake (my scheduled is quite full though, but this is just a test for me. Others can take over if I fail or just do it separately), then post it here.
My current ideas are:
FTL: Faster Than Light
Meatboy
Maybe Broforce, but that would just be interesting from the destructible world part.
The problem with this is that they are all indie games. For example, if I make a very precise remake of FTL then that could actually be negative and seen as copying other people ideas. And then if I release them as freeware then people would think I want to rip off the original devs.
So what you guys think? If anyone has a game they would like me to try to remake (my scheduled is quite full though, but this is just a test for me. Others can take over if I fail or just do it separately), then post it here.
My current ideas are:
FTL: Faster Than Light
Meatboy
Maybe Broforce, but that would just be interesting from the destructible world part.
The problem with this is that they are all indie games. For example, if I make a very precise remake of FTL then that could actually be negative and seen as copying other people ideas. And then if I release them as freeware then people would think I want to rip off the original devs.
30
General ENIGMA / AA Regression Discussion (Split from Git Proposal topic)
« on: June 05, 2013, 04:33:44 pm »
I want to mention that there have been other features removed by Robert like primitive AA, which, without anything in its place, also is regress. So you all do it.
And mouse_x/y is the MOST USED thing in GM/ENIGMA. I for one have it in EVERY game/program I have made in the past 10 years (yes, I used GM since 2002). If you make anything with mouse (and most people do) then it is used. So the 3rd point by poly was extremely weird as himself is quite experienced with GM and ENIGMA.
And mouse_x/y is the MOST USED thing in GM/ENIGMA. I for one have it in EVERY game/program I have made in the past 10 years (yes, I used GM since 2002). If you make anything with mouse (and most people do) then it is used. So the 3rd point by poly was extremely weird as himself is quite experienced with GM and ENIGMA.