Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

254 Neutral

About luorax

  • Rank
  1. Hey guys! I've been working on an entity component system in that very little spare time that I've had this past week. The main goals were these: improve cache coherency split up that gigantic Entity blob class I've had into multiple pieces reduce duplicate code Before we continue, let's note that I'm using C++. So I've managed to set up two template classes: one for type abstraction (a component type object, basically for storing the instances in a huge, continuous vector for fast updates) and one for the component base class, from which the actual component classes need to inherit. I was planning on using unsigned ID's for attaching the components to the container/Entity objects, and updating all the component types sequentially, by traversing the component types and updating all the component instances. It's all fine and such, I'm more or less satisfied with what I've got in such little time. However, I've ran into a problem: parent-child relation. The only thing that comes to my mind is transformations, but those most definitely require parent entities to be updated before their children. In the old (current) system it is done by storing the all the root entities (entities with no parent entity) in a vector, and updating each of these and all their children in a loop. It uses indirection, though, and the whole purpose of this new system is to improve cache coherence by avoiding these jumps. So, my question is: how would you get around this problem? What is the traditional or common way of solving this issue? It's clear that there is currently only one component that requires parent information (transformation), and there ain't gonna be more in the future either (only UI transformations, most likely), so I could give these special attention, but I'd like to know if there is a better, preferably generic way of solving this issue. Thans for reading, and also thanks in advance for any help I get! P.s.: Here is the component header that I've managed to put together. Please bear in mind though that it's untested, and was made in a very short period of time, so it's highly likely to change in the future. http://pastebin.com/tEjkqjY4
  2. Hey there!   I've got an issue that I've already wasted on more hours than it deserves, and hasn't been able to solve it, so I'm asking for help.   I've got a persistently mapped buffer object that is bound through a named shader storage buffer bindpoint, which contains the parameters for all my terrain instances. Originally I was using a statically sized UBO with the maximum possible terrain count, and did the same for other type of game objects (materials, light sources, entities, etc.), but while they worked fine on my desktop configuration, the arrays were too large for the GPU in my laptop, for example, so I decided to try a different route. And it's been working fine for everything else, but the terrain part of the code is kinda bugged.   It's highly WIP, I'm experimenting with a lot of different ideas - you may suggest things not related to my problem, but please keep this in mind!   The C-side structure looks like this: struct TerrainData     {         glm::mat4 m_model;         glm::mat4 m_normal;         GLint m_layerCount;         GLfloat m_tileBias;         GLfloat m_tileScale;         GLfloat m_pad;         GLuint m_layer0;         GLuint m_layer1;         GLuint m_layer2;         GLuint m_layer3;         GLuint m_layer4;         GLuint m_layer5;         GLuint m_layer6;         GLuint m_layer7;         GLuint m_layer8;         GLuint m_layer9;         GLuint m_layer10;         GLuint m_layer11;         GLuint m_layer12;         GLuint m_layer13;         GLuint m_layer14;         GLuint m_layer15;         GLuint m_layer16;         GLuint m_layer17;         GLuint m_layer18;         GLuint m_layer19;         GLuint m_layer20;         GLuint m_layer21;         GLuint m_layer22;         GLuint m_layer23;         GLuint m_layer24;         GLuint m_layer25;         GLuint m_layer26;         GLuint m_layer27;         GLuint m_layer28;         GLuint m_layer29;         GLuint m_layer30;         GLuint m_layer31;     }; Some pretty basic data: model/normal matrices, triplanar parameters, material indices, etc.   The way I access it in GLSL is like this: ////////////////////////////////////////////////// //  Terrain parameters struct TerrainParameters {     mat4 mModel;     mat4 mNormal;     int iLayerCount;     float fTileBias;     float fTileScale;     uvec4 uLayers[8]; }; layout (std140, binding=STORAGE_BINDING_ACTOR) buffer TerrainData {     TerrainParameters terrainParameters[]; }; #define _terrain terrainParameters[terrainId-1] ////////////////////////////////////////////////// //  Model matrix mat4 getModelMatrix(uint terrainId) {     return _terrain.mModel; } ////////////////////////////////////////////////// //  Normal matrix mat4 getNormalMatrix(uint terrainId) {     return _terrain.mNormal; } ////////////////////////////////////////////////// //  Tile bias/scale float getTileBias(uint terrainId) {     //return 0.5;     return _terrain.fTileBias; } float getTileScale(uint terrainId) {     //return 0.00025;     return _terrain.fTileScale; } ////////////////////////////////////////////////// //  Layers int getLayerCount(uint terrainId) {     //return 2;     return _terrain.iLayerCount; } uint getLayerId(uint terrainId, uint index) {     //return index+1;          if (index>31)         return 0;     return _terrain.uLayers[index/4][index%4]; } Now here is what's wrong: if I comment out all the layer getters, and use the burnt-in magic numbers currently in the comments, then the model and normal matrices read back are the proper ones. If I try to access any of the layer attributes (tile bias/scale, layer count, material indices), then while I can get back the appropriate value, my model and normal matrices are screwed. I tested this by using a "magic model matrix" in the vertex shader - the vertices appear, the materials are okay, but the normals are wrong.   Does anyone have any idea what could be wrong? I've already tried multiple things (unrolling that array in the struct, using std430 just to name the most common mistakes people make), none of them helped, and I'm out of ideas.   P.s: Here are 2 screenshots, just to give you a grasp of an idea what things look like. I just threw together a bunch of random things (height map, blend maps, materials, etc) I could find on the internet, but for development, they work just fine. (Triplanar mapping also looks like crap, but that's the topic of a different thread) Without magic numbers: all the normals are wrong (bottom right quad). Specular lighting is also screwed up, only a huge bright circle appears, as it can be seen on the first quad With magic numbers: correct normals, correct specular lighting. But it's fully driven by magic numbers.   [EDIT] So, I've tested it on my laptop too, and it works perfectly on it, with a gt635m GPU. My AMD has an r7 260x, and it's bugged there. Hmmpf.
  3. luorax

    3D UI transformation matrix

    Okay, so I'm setting up my projection matrix like this now (and no view matrix, it's not needed): glm::mat4 projection=glm::perspective(glm::radians(90.0f),1.0f,0.0f,width); //aspect ratio is 1.0, no correction needed This allows me to use positions and sizes from the [-1,1] interval. a.k.a. directly mapping my UI components to the screen. It's not as nice as using window coordinates, but it has an even better advantage: it scales with window size / resolution. Using window coordinates is bad because I noticed that if I played around with my window's size, things would randomly become visible/invisible as they go out of screen - this solution, however, does not suffer from that problem.   I still need to fix a few things (text rendering, image borders do not show up just yet, mouse clicking on buttons), but I think I'll be good, once I redo my UI using the new system.
  4. luorax

    3D UI transformation matrix

    No, you got it right. And no, I'm not new to graphics programming either, it's just I have this specific problem which I'd like to solve in this specific way, but sadly, it doesn't seem to work out as I imagined.   What I was trying to do in the code above is create a view matrix at the center of the window and look at the elements from there, but I realised it myself that it won't work like that and now I'm in the process of rethinking the whole problem.   Doing the UI in world space is what I've been thinking of,too. My problem with that though is that I'm still not sure what kind of projection matrix I should use (propably a custom one, and not the projection matrix used by the 'camera', so changing the camera would not affect the UI - but I don't know if a fov of 90 degrees is correct for it) and that I'd lose my ability to position my UI elements in window space, which is something I really liked and would like to keep, if possible, because that eases my work a lot. Or maybe I would, and maybe I'm just not understanding this more advanced projection matrix, that incorporates things like aspect ratio and field of view - the one we learned about at school is much simpler. In all honesty, I haven't taken the time to investigate closely the more complex perspective matrix, I just relied on glm creating it for me, and it looks like now is the time when I see why it was a mistake.   I'm off for today, but I think I'm gonna have to do some major changes to get this thing done, much more than I've anticipated.
  5. luorax

    3D UI transformation matrix

    I've edited my post, I didn't word it properly. I can render things in 2D, that's a no-brainer, my problem is with creating a proper perspective projection matrix. The one I have in the second code tag does not work. I've been working on other stuff all day, might give it another go later, propably in the evening or so.
  6. Hello there community!   I'm trying to extend my 2D UI to the third dimension, to allow 3D components. When I first played Crysis 3 I really liked the 3D hud and I'd like to be able to create similar UI components (for those who're not familiar with Crysis 3, here is a screenshot  - I'm talking about the map and weapon components).   This is how I'm rendering my UI right now: GLfloat width=(GLfloat) CEngine::getInstance().getWindow()->getWidth(); GLfloat height=(GLfloat) CEngine::getInstance().getWindow()->getHeight(); glm::mat4 viewProj=glm::ortho(0.0f,width,0.0f,height,2.0f*width,0.0f); //////////////////////////////////////////////////// // Render all the visible UI elements for (auto it=s_uiElements.begin();it!=s_uiElements.end();it++) { CUIElement* element=*it; if (element->m_visible) {        element->m_ubo->bindBase(CShader::UNIFORM_BINDPOINT_UI);         element->m_transform=viewProj*element->m_model;         element->uploadData();        element->renderThis(); } } A simple perspective projection, nothing fancy.   This is how I'm trying to set up the perspective projection: glm::mat4 projection=glm::perspective(glm::radians(90.0f),width/height,0.0f,width); glm::mat4 view=glm::lookAt(glm::vec3(width*0.5f,height*0.5f,0.0f),glm::vec3(width*0.5f,height*0.5f,-1.0f),glm::vec3(0.0f,1.0f,0.0f)); glm::mat4 viewProj=projection*view; But it just doesn't work.   Could someone tell me what I'm doing wrong, and how I could approach this? I just can't figure it out on my own.   P.s: as for the model matrices and vertex data: they're rendered as quads ((0,0),(0,1),(1,0),(1,1)) and the model matrix takes them into the appropriate window position ((0,0)-(width,height)) and size. [EDIT]:   For clarification: I have all the vertex data, model matrix, and all the like set up properly. I've been able to render 2D elements just fine for months, but I want to move to 3D now. All I need is a proper projection/view+projection matrix, that I could use to take the UI element's Y rotation and give it some depth.   My vertex data is set up such that each vertex falls into the vec2(0,0)-vec2(window_width,window_height) range, and the Z component is 0 by default, but it can be changed with rotations.   I have recently added support for various fill (normal / radial) and color (constant / gradient / radial gradient) methods, and I happen to have a screenshot of what I've got right now: [link]
  7. luorax

    Introduction to Octrees

    Only one comment? Really? Man, this tutorial is amazing! I plan on implementing something similar into my game engine in the near future and I'm sure I will be able to do it using this tutorial only!   Thank you very much for this amazing work <3
  8. Okay, I managed to solve it. It had nothing to do with my setup, nor with my shaders. The shaders are OK. and so is my setup. The problem is with these lines: ... vPos=particleData[0].vPos+particleData[0].vVelocity*commonParameters.fDeltaTime; ... fLife=particleData[0].fLife-commonParameters.fDeltaTime; ... The thing is, commonParameters comes from an UBO, which is bound by the Renderer object. It remains bound throughout the whole life of the program, but the first update is invoked before the first render, before letting the Renderer bind it.
  9. I've been working on a particle implementation lately, but I couldn't even get past the first 'render', a.k.a. the update part, because my program crashes immediately after issuing the draw command. It's driving me nuts, I've been messing with this thing for like half a day by now and I still can't see what's wrong.   I figured I wouldn't post my actual code as almost everything is done through wrappers (except for the query and transform feedback objects), so I'm going to show you what GLIntercept captures: //... // generate the feedback and query objects glGenTransformFeedbacks(2,07CF4530) glGenQueries(1,07CF4538) // generate the first vao glGenVertexArrays(1,11F328AC) glBindVertexArray(395) // generate the storage buffer for the first TFB glGenBuffers(1,12164D40) glBindBuffer(GL_ARRAY_BUFFER,1222) // init storage for it and fill it with the default data glBufferData(GL_ARRAY_BUFFER,56,00F09868,GL_DYNAMIC_DRAW) // setup the VAO - remember, the offset parameter is a pointer, thus its value is displayed in hexa // iType glEnableVertexAttribArray(0) glVertexAttribPointer(0,1,GL_INT,false,56,00000000) // iLevel glEnableVertexAttribArray(1) glVertexAttribPointer(1,1,GL_INT,false,56,00000004) // vPos glEnableVertexAttribArray(2) glVertexAttribPointer(2,3,GL_FLOAT,false,56,00000008) // vVelocity glEnableVertexAttribArray(3) glVertexAttribPointer(3,3,GL_FLOAT,false,56,00000014) // fLife glEnableVertexAttribArray(4) glVertexAttribPointer(4,1,GL_FLOAT,false,56,00000020) // vColor glEnableVertexAttribArray(5) glVertexAttribPointer(5,4,GL_FLOAT,false,56,00000024) // fSize glEnableVertexAttribArray(6) glVertexAttribPointer(6,1,GL_FLOAT,false,56,00000034) // unbind the VAO, no longer needed glBindVertexArray(0) // bind the first TFB and show it its VBO glBindTransformFeedback(GL_TRANSFORM_FEEDBACK,1) glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,0,1222) glBindTransformFeedback(GL_TRANSFORM_FEEDBACK,0) glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER,0) // ... do the same for the second TFB glGenVertexArrays(1,11F32A1C) glBindVertexArray(396) glGenBuffers(1,12164D68) glBindBuffer(GL_ARRAY_BUFFER,1223) glBufferData(GL_ARRAY_BUFFER,56,00F09868,GL_DYNAMIC_DRAW) glEnableVertexAttribArray(0) glVertexAttribPointer(0,1,GL_INT,false,56,00000000) glEnableVertexAttribArray(1) glVertexAttribPointer(1,1,GL_INT,false,56,00000004) glEnableVertexAttribArray(2) glVertexAttribPointer(2,3,GL_FLOAT,false,56,00000008) glEnableVertexAttribArray(3) glVertexAttribPointer(3,3,GL_FLOAT,false,56,00000014) glEnableVertexAttribArray(4) glVertexAttribPointer(4,1,GL_FLOAT,false,56,00000020) glEnableVertexAttribArray(5) glVertexAttribPointer(5,4,GL_FLOAT,false,56,00000024) glEnableVertexAttribArray(6) glVertexAttribPointer(6,1,GL_FLOAT,false,56,00000034) glBindVertexArray(0) glBindTransformFeedback(GL_TRANSFORM_FEEDBACK,2) glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,0,1223) glBindTransformFeedback(GL_TRANSFORM_FEEDBACK,0) glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER,0) //... // no rasterization needed glEnable(GL_RASTERIZER_DISCARD) // bind program glUseProgram(32) // bind the uniform buffer glBindBufferBase(GL_UNIFORM_BUFFER,9,1221) // fill it with the default data ('upload' does its own binding, that's why the double bind calls) glBindBuffer(GL_UNIFORM_BUFFER,1221) glBufferData(GL_UNIFORM_BUFFER,64,0513FE84,GL_STREAM_DRAW) // bind the target TFB glBindTransformFeedback(GL_TRANSFORM_FEEDBACK,2) // bind the target buffer (stored in the TFB, this was put here for testing, but doesn't solve the problem) glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,0,1223) //1223, a.k.a. the second buffer - this is O.K. // query the number of particles written (stored in the TFB, but it's useful information) glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN,1) // begin the TFB glBeginTransformFeedback(GL_POINTS) // bind the source VAO glBindVertexArray(395) //395, a.k.a. the first VAO - this is alright too // 'draw' them glDrawArrays(GL_POINTS,0,1) // go super MAD here And here is my update shader: ////////////////////////////////////////////////// // Helpers #define TYPE_REGULAR 0 #define TYPE_GENERATOR 1 struct ParticleData { int iType; int iLevel; vec3 vPos; vec3 vVelocity; float fLife; vec4 vColor; float fSize; }; ////////////////////////////////////////////////// // Vertex base shader VS_base(in int iType: 0, in int iLevel: 1, in vec3 vPos: 2, in vec3 vVelocity: 3, in float fLife: 4, in vec4 vColor: 5, in float fSize: 6, out ParticleData particleData) { particleData.iType=iType; particleData.iLevel=iLevel; particleData.vPos=vPos; particleData.vVelocity=vVelocity; particleData.fLife=fLife; particleData.vColor=vColor; particleData.fSize=fSize; // this vertex shader is used for rendering too, so set it - // removing it doesn't solve the problem gl_Position=vec4(vPos,1.0); } ////////////////////////////////////////////////// // Update shader GS_update(in ParticleData particleData[], out int iType: 0, out int iLevel: 1, out vec3 vPos: 2, out vec3 vVelocity: 3, out float fLife: 4, out vec4 vColor: 5, out float fSize: 6) { ////////////////////////////////////////////////// // Update the particle iType=particleData[0].iType; iLevel=particleData[0].iLevel; vPos=particleData[0].vPos+particleData[0].vVelocity*commonParameters.fDeltaTime; vVelocity=particleData[0].vVelocity; fLife=particleData[0].fLife-commonParameters.fDeltaTime; vColor=particleData[0].vColor; fSize=particleData[0].fSize; ////////////////////////////////////////////////// // Keep if it's still alive ... if (fLife<0.0) { EmitVertex(); EndPrimitive(); ////////////////////////////////////////////////// // ... and generate new particles if (iType==TYPE_GENERATOR) { // currently there is not enough storage allocated, but the relational operator // at the top is reversed so that it wouldn't output a single particle, for now // but even so, it still doesn't work, so I suspect that the problem is with the // source. But I can't say that for sure, because OpenGL provides you with such // a vast amount of debugging tools that I'm not even sure which one to use </sarcasm> #define GEN_COUNT 5 for (int i=0;i<GEN_COUNT;i++) { iType=TYPE_REGULAR; iLevel=particleData[0].iLevel; vPos=particleData[0].vPos; vVelocity=vec3(rand(vec2(1.0,0.0),-1.0,1.0),rand(vec2(0.0,1.0),0.0,1.0),rand(vec2(1.0,0.0),-1.0,1.0))*25.0; fLife=1.0; vColor=vec4(1.0); fSize=1.0; EmitVertex(); EndPrimitive(); } } } } Any help is appreciated.
  10. luorax

    OpenGL 3.3+ Tutorials

    Congratulations for your graduation Michal!   Your tutorials are prime quality, and were a lot of help for me when I started learning about OpenGL. And they continued to be even after becoming more experienced: the font rendering one had a lot of useful information about FreeType, for example, even though I knew how to set up projections and such.   BTW, I have a question for you in regards to future tutorial content (or you can think of this as a requestion/suggestion for an upcoming tutorial): now that you've released your particle tutorial, and even based your graduation thesis on particles, do you plan on doing one more advanced type of particles, like ribbons and beams? They're like the most awesome particle types, and yet you cannot find a SINGLE tutorial on them, or even a clue about where and how you should start. I plan on starting to work on my own particle implementation once I'm done with SSAO, so I might be able to come up with something on my own once I have more experience with GPU soft particles, but it'd be helpful if there was at least a demo code, if not a tutorial, that'd help immensely.   Congratulations again, and keep up the good work!
  11. Turns out the material has actual bump textures and not normal ones, so that's what causing the problems. I'll try to convert them to normal maps somehow and see if it works.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!