• Announcements

    • khawk

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

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


  • Content count

  • Joined

  • Last visited

Community Reputation

199 Neutral

About Rarosu

  • Rank
  1. Calling glFinish() after the first draw call seems to fix this problem. Obviously this is not ideal as it will block the execution until the draw call has finished, but it will at least fix the symptoms.
  2. @Glass_Knife Hah. It it a frightening thought to think how many hidden driver errors there are out there.   Updating the Intel driver to did not solve the problem unfortunately. The only solution I can see currently is revert to using glUniform* or create separate uniform buffer objects for each instance. Which sucks. If I find out anything else I'll update this thread.   - Rarosu
  3. Running this project on an Nvidia card instead yielded the expected results... Two boxes. Either Nvidia is lenient with whatever error I might be doing, or this Intel driver has some bug. I will look into updating my drivers and see if this fixes the problem.
  4. @beans222 I don't think that is the problem in this case, but to be safe, I have tried changing the uniform data to an array of 4 floats and will include it in the edit.
  5. Thanks for the reply, GlassKnife, I'll edit the original post with the code.   I have reduced the issue to where I know there is something going on with the uniform bindings. I have tried making a separate program, VBO and VAO for the second instance and the same problem occurs. When I make a separate uniform buffer object however and fill it with the same data, it works. That is, the difference between: glUseProgram(program); glBindVertexArray(vao); // Instance is rendered. uniform_buffer_data.offset = 1.3f; glBindBufferBase(GL_UNIFORM_BUFFER, UNIFORM_BINDING, uniform_buffer); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformBuffer), &uniform_buffer_data); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // This instance is also rendered. ubo_data2.offset = -0.4f; glBindBufferBase(GL_UNIFORM_BUFFER, UNIFORM_BINDING, ubo2); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformBuffer), &ubo_data2); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); And this: glUseProgram(program); glBindVertexArray(vao); // This instance is no longer visible. uniform_buffer_data.offset = 1.3f; glBindBufferBase(GL_UNIFORM_BUFFER, UNIFORM_BINDING, uniform_buffer); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformBuffer), &uniform_buffer_data); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // And only this one is rendered. uniform_buffer_data.offset = -0.4f; glBindBufferBase(GL_UNIFORM_BUFFER, UNIFORM_BINDING, uniform_buffer); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformBuffer), &uniform_buffer_data); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); As for checking the state, I am not sure what to look for in this scenario. I tried apitrace at your suggestion (which seems awesome) and the state looks fine to me; as I would expect it.
  6. Hello GameDev!   I am porting an OpenGL 4.4 application to OpenGL 3.1 to get it to run on my Intel HD Graphics 3000 card (on my laptop). So far, things have been going well, but I ran into a problem when rendering more than one instance using the same vertex buffer (just changing the uniform buffer between the draw calls). When I do this, only the last instance is rendered. The non-ported code did not exhibit this problem and I just cannot see what I might have done to cause it to fail.   I have managed to isolate the bug in a minimal sample: http://pastebin.com/87DQhdrS #include <SDL2/SDL.h> #include <GL/gl3w.h> #include <iostream> #include <string> const int OPENGL_MAJOR = 3; const int OPENGL_MINOR = 1; const int UNIFORM_BINDING = 1; const char* VERTEX_SOURCE = "#version 140 \n" " \n" "in vec2 in_position; \n" " \n" "layout(std140) uniform UniformBuffer \n" "{ \n" " vec4 offset; \n" "}; \n" " \n" "void main() \n" "{ \n" " gl_Position = vec4(in_position, 0.0f, 1.0f);\n" " gl_Position.x += offset.x; \n" "} \n"; const char* FRAGMENT_SOURCE = "#version 140 \n" " \n" "out vec4 out_color; \n" " \n" "void main() \n" "{ \n" " out_color = vec4(1.0f, 1.0f, 1.0f, 1.0f); \n" "} \n"; struct UniformBuffer { float offset[4]; }; SDL_Window* window = nullptr; SDL_GLContext glcontext = nullptr; unsigned int viewport_width = 800; unsigned int viewport_height = 600; bool running = true; GLuint vertexShader = 0; GLuint fragmentShader = 0; GLuint program = 0; GLuint position_vbo = 0; GLuint vao = 0; UniformBuffer uniform_buffer_data; GLuint uniform_buffer = 0; void initialize(); void loadResources(); GLuint compileShader(const char* source, GLuint type); void linkProgram(GLuint program); void run(); void handleEvents(); void render(); int main(int argc, char* argv[]) { initialize(); loadResources(); run(); return 0; } void initialize() { if (SDL_Init(0) != 0) { throw std::runtime_error("Failed to initialize SDL"); } window = SDL_CreateWindow("gl3", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, viewport_width, viewport_height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if (window == nullptr) { throw std::runtime_error("Failed to create SDL window"); } SDL_GLcontextFlag flags = SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG; #ifndef NDEBUG flags = (SDL_GLcontextFlag)(flags | SDL_GL_CONTEXT_DEBUG_FLAG); #endif SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_MAJOR); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, OPENGL_MINOR); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, flags); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0); glcontext = SDL_GL_CreateContext(window); if (glcontext == nullptr) { throw std::runtime_error("Failed to create OpenGL context"); } if (gl3wInit() != 0) { throw std::runtime_error(std::string("Failed to initialize gl3w")); } if (gl3wIsSupported(OPENGL_MAJOR, OPENGL_MINOR) != 1) { throw std::runtime_error("OpenGL version not supported"); } glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glViewport(0, 0, viewport_width, viewport_height); SDL_GL_SetSwapInterval(1); } void loadResources() { // VBOs. float positions[] = { -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f }; glGenVertexArrays(1, &vao); glBindVertexArray(vao); glGenBuffers(1, &position_vbo); glBindBuffer(GL_ARRAY_BUFFER, position_vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, positions, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); // Shaders. vertexShader = compileShader(VERTEX_SOURCE, GL_VERTEX_SHADER); fragmentShader = compileShader(FRAGMENT_SOURCE, GL_FRAGMENT_SHADER); program = glCreateProgram(); glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); linkProgram(program); glUniformBlockBinding(program, glGetUniformBlockIndex(program, "UniformBuffer"), UNIFORM_BINDING); // UBOs. uniform_buffer_data.offset[0] = 0.0f; uniform_buffer_data.offset[1] = 0.0f; uniform_buffer_data.offset[2] = 0.0f; uniform_buffer_data.offset[3] = 0.0f; glGenBuffers(1, &uniform_buffer); glBindBufferBase(GL_UNIFORM_BUFFER, UNIFORM_BINDING, uniform_buffer); glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformBuffer) * sizeof(float), &uniform_buffer_data, GL_DYNAMIC_DRAW); } GLuint compileShader(const char* source, GLuint type) { GLuint shader = glCreateShader(type); glShaderSource(shader, 1, &source, nullptr); glCompileShader(shader); GLint status; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { GLint logSize; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize); std::string log; if (logSize > 0) { int written; log.resize(logSize); glGetShaderInfoLog(shader, logSize, &written, &log[0]); } throw std::runtime_error("Failed to compile shader: " + log); } return shader; } void linkProgram(GLuint program) { glLinkProgram(program); GLint status; glGetProgramiv(program, GL_LINK_STATUS, &status); if (status != GL_TRUE) { GLint logSize; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logSize); std::string log; if (logSize > 0) { int written; log.resize(logSize); glGetProgramInfoLog(program, logSize, &written, &log[0]); } throw std::runtime_error("Failed to link program: " + log); } } void run() { while (running) { handleEvents(); render(); } } void handleEvents() { SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: { running = false; } break; case SDL_WINDOWEVENT: { switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: { viewport_width = event.window.data1; viewport_height = event.window.data2; glViewport(0, 0, viewport_width, viewport_height); } break; } } break; } } } void render() { glClear(GL_COLOR_BUFFER_BIT); glUseProgram(program); glBindVertexArray(vao); uniform_buffer_data.offset[0] = 1.3f; glBindBufferBase(GL_UNIFORM_BUFFER, UNIFORM_BINDING, uniform_buffer); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformBuffer) * sizeof(float), &uniform_buffer_data); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); uniform_buffer_data.offset[0] = -0.4f; glBindBufferBase(GL_UNIFORM_BUFFER, UNIFORM_BINDING, uniform_buffer); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformBuffer) * sizeof(float), &uniform_buffer_data); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); SDL_GL_SwapWindow(window); } I am using SDL2 and GL3W and I am working in Visual Studio 2013 on Windows 10. The biggest change when I ported was that I no longer could specify the uniform binding point in the shader, but had to use glUniformBlockBinding instead. Anyone familiar with this version of OpenGL who could tell me if I am doing something stupid?   Cheers! - Rarosu
  7. Thank you for the reply! I have encountered the Pacejka model before when researching, but it seemed like it was mostly used for more realistic simulations when I feel like there should be relatively simple model to get a car to lose grip when the traction exceeds the maximum friction. I might look into it again and actually implement it, but I am hesitant to complicate the model with magic equations before I have a working simple model. Additionally, I have also tried to keep track of the wheel spin and calculate the slip ratio before (as I believe is an input to the Pacejka formulas), but it always ended up being rather unstable as the traction could change pretty drastically for low slip ratios and cause the wheel spin to fluctuate.
  8. That makes intuitive sense to me, but I am not sure where it would fit in. No resources I have looked at has had an explicit opposing friction force (apart from rolling friction). It feels like the radius of the circle of traction would be smaller when the car starts to slide (making the maximum forward/backward traction and cornering forces smaller which makes it more difficult to correct the car trajectory). However, I need to check versus the circle to know whether I am sliding... So, either I am wrong in how I am detecting when the car starts to slide, or I will need a state that remains across frames.
  9. Hello all!   I have been working on a simple top-down 2D car simulator and have some questions to anyone who is experienced with this. The main problem I have is how to simulate a wheel losing grip. I have been reading Brian Beckman's series on racing and I understand that the tires have an adhesive limit and that the circle/ellipsis of traction can be used to know whether a wheel is gripping or not. Am I right to presume that the amount of traction on a tire needs to be capped to the circle? This is my per-frame code at the moment:   float speed = glm::length(velocity_local); // Calculate weight distribution. float weight = description.mass * G; float wheelbase = description.cg_to_front_axle + description.cg_to_back_axle; float front_weight = (description.cg_to_back_axle / wheelbase) * weight - (description.cg_height / wheelbase) * description.mass * acceleration_local.x; float rear_weight = (description.cg_to_front_axle / wheelbase) * weight + (description.cg_height / wheelbase) * description.mass * acceleration_local.x; // Assume the wheels are rolling and calculate the engine torque. float wheel_angular_velocity = velocity_local.x / description.wheel_radius; float transmission = description.gear_ratios[gear] * description.differential_ratio * description.transmission_efficiency; float engine_rpm = ANGULAR_VELOCITY_TO_RPM * wheel_angular_velocity * transmission; float engine_torque = throttle ? lerp_curve(description.torque_curve, engine_rpm) : 0.0f; // Simplified traction model - use the torque on the wheels. float drive_torque = engine_torque * transmission; float traction_force = drive_torque / description.wheel_radius; // Calculate the braking torque on the wheels. float braking_torque = reverse ? 3500 : 0; float braking_force = -braking_torque / description.wheel_radius * glm::sign(velocity_local.x); // Calculate the lateral slip angles and determine the lateral cornering force. float front_angular_velocity = car_angular_velocity * description.cg_to_front_axle; float rear_angular_velocity = -car_angular_velocity * description.cg_to_back_axle; float slip_angle_front = std::atan2(velocity_local.y + front_angular_velocity, std::abs(velocity_local.x)) - glm::sign(velocity_local.x) * steer_angle; float slip_angle_rear = std::atan2(velocity_local.y + rear_angular_velocity, std::abs(velocity_local.x)); float cornering_force_front = front_weight * -description.cornering_stiffness * slip_angle_front; float cornering_force_rear = rear_weight * -description.cornering_stiffness * slip_angle_rear; // The wheels have a limited maximal traction before they start to slide. float traction_circle_radius = 0.8; glm::vec2 front_total_traction = glm::vec2(0, cornering_force_front * std::cos(steer_angle)); glm::vec2 rear_total_traction = glm::vec2(traction_force + braking_force, cornering_force_rear); bool front_slipping = false; float front_total_traction_length = glm::length(front_total_traction); if (front_total_traction_length / front_weight >= traction_circle_radius) { front_total_traction /= front_total_traction_length; front_total_traction *= traction_circle_radius * front_weight; front_slipping = true; } bool rear_slipping = false; float rear_total_traction_length = glm::length(rear_total_traction); if (rear_total_traction_length / rear_weight >= traction_circle_radius) { rear_total_traction /= rear_total_traction_length; rear_total_traction *= traction_circle_radius * rear_weight; rear_slipping = true; } // Calculate the torque on the car body and integrate car yaw rate and orientation. float cornering_torque_front = front_total_traction.y * description.cg_to_front_axle; float cornering_torque_rear = rear_total_traction.y * description.cg_to_back_axle; float car_torque = std::cos(steer_angle) * cornering_torque_front - cornering_torque_rear; float car_angular_acceleration = car_torque / description.inertia; car_angular_velocity += car_angular_acceleration * dt; orientation += car_angular_velocity * dt; // Calculate the wind drag force on the car. Simplification that the area facing the velocity direction is the front. float area = description.height * 2.0f * description.halfwidth; float drag_multiplier = 0.5f * description.air_density * area * description.drag_coefficient; glm::vec2 drag_resistance = -drag_multiplier * speed * velocity_local; // Calculate the rolling friction force on the car. glm::vec2 rolling_resistance = glm::vec2(-description.wheel_rolling_friction * velocity_local.x, 0); // Sum the forces on the car's CG and integrate the velocity. glm::vec2 force = rear_total_traction + front_total_traction + drag_resistance + rolling_resistance; acceleration_local = force / description.mass; velocity_local += acceleration_local * dt; // Calculate the acceleration and velocity in world coordinates and integrate world position. float sn = std::sin(orientation); float cs = std::cos(orientation); acceleration.x = cs * acceleration_local.x - sn * acceleration_local.y; acceleration.y = sn * acceleration_local.x + cs * acceleration_local.y; velocity.x = cs * velocity_local.x - sn * velocity_local.y; velocity.y = sn * velocity_local.x + cs * velocity_local.y; position += velocity * dt;   This gets me a car that can accelerate and steer, however the tires never seem to lose grip the way I expect them to. I can move at 200 km/h and make a abrupt turn without spinning (the car simply moves in approximately the same arc as when going slow). Am I missing some step to simulate a sliding car apart from capping the traction?   Also, as a side question, is using the torque on the rear wheels as the forward traction force an acceptable approximation? I saw this being done in "on the envelope" calculations by Brian, ignoring slip ratios and wheel turn rate integration. However, I am not sure how correct this actually is.   Any input is appreciated!  
  10. Great info and links, Sean! I'll definitely have a read through them, it is more information than I've found previously and it's nice to get something substantial on the subject. I'm considering using WebSockets or something for the connection to the central web server, since it is already suitable for that purpose. WebRTC is the option I'm considering between the browsers when game state data needs to be distributed. I'll read up on the protocol and see what it can offer though, and try out some implementations and see what works and what doesn't.
  11. My plan is to make a co-op platformer/action game for a small group of people, so the cheating aspect is hopefully not too relevant in this case, even though I think it is possible to solve if one of the clients are acting server. My current idea is to use the server as a broker of kind. Let one of the clients (the host) create the game via a web form. The server will generate a random hash and send it back in the URL of the response. The host can send the URL to any player they wish to invite. A peer that connects with the URL will be matched by the server with the host that is associated with the given hash. The server will respond with the connection details to the host, and the peer can connect to the host. It /feels/ straightforward and I'm going to experiment with it, but I'm not sure if I'm on the right path here. I'm mostly looking to alleviate the web server of having to mirror all the game messages and instead only focusing on the whole setting up the connections. The latency of the game itself will be another challenge :D
  12. Hello! I've gotten interested in making multiplayer games using HTML5. I've looked into WebSockets via socket.io, but I was disappointed that all the communication seemed to have to go through the server. What I had been hoping for was to use the web server only as a kind of matchmaker and resource deliverer, and let the clients send the game state updates between each other (with the client that created the game acting as the game server). Without this kind of direct communication between the clients, it seems like the web server would get an unproportionate workload, especially with a couple of games running. I found that WebRTC could be used for peer to peer communication in browsers, but I haven't found much information on the subject. Has anyone used this for a game yet? Is there any proper documentation available? How realistic is it to implement peer-to-peer communication via the browser at the current date? :) I would love to hear the experiences of anyone else who has been developing multiplayer games for the web and what the common solutions are, if any.
  13. Hello, I'm getting a problem when creating an effect using the Effects11 framework: [code] D3D11: ERROR: ID3D11Device::CreateVertexShader: Shader must be vs_4_0 or vs_4_1. Shader version provided: vs_5_0 [ STATE_CREATION ERROR #167: CREATEVERTEXSHADER_INVALIDSHADERTYPE ] First-chance exception at 0x000007fefde9cacd in WarSettlers.exe: Microsoft C++ exception: _com_error at memory location 0x0018e620.. D3D11: ERROR: ID3D11Device::CreatePixelShader: Shader must be ps_4_0 or ps_4_1. Shader version provided: ps_5_0 [ STATE_CREATION ERROR #193: CREATEPIXELSHADER_INVALIDSHADERTYPE ] First-chance exception at 0x000007fefde9cacd in WarSettlers.exe: Microsoft C++ exception: _com_error at memory location 0x0018e620.. [/code] So my card isn't supporting a shader version higher than 4.1. Fair enough. I can switch adapter and then it works fine. My problem is that D3DX11CreateEffectFromMemory from which these errors originate returns S_OK. And then the program breaks because it cannot find a bound vertex and pixel shader. I'd really like to be able to catch this and output a proper error to the user, so my question is if there is any way of detecting this? The code I use for compiling and creating an effect below: [code] // Compile the effect ID3D10Blob* shader; ID3D10Blob* errors; HRESULT result = D3DX11CompileFromFile("Resources/Effects/BasicColor.fx", NULL, NULL, NULL, "fx_5_0", D3D10_SHADER_ENABLE_STRICTNESS | D3D10_SHADER_DEBUG, 0, NULL, &shader, &errors, NULL); if (FAILED(result)) { std::string errorMessage; if (errors != NULL) { errorMessage = static_cast(errors->GetBufferPointer()); } else { errorMessage = "Could not find effect file"; } throw DirectXErrorM(result, errorMessage); } result = D3DX11CreateEffectFromMemory(shader->GetBufferPointer(), shader->GetBufferSize(), 0, GetD3D().GetDevice().Resource(), &m_effect.Resource()); if (FAILED(result)) { throw DirectXErrorM(result, "Failed to create effect from compiled blob."); } [/code] Does anyone have any idea on how to check if the vertex- and pixel shader have been actually created by the effect?
  14. You probably do not want to seed the random number generator with GetElapsedTime(). This function will give you the time since the application has started, which should be approximately the same number every time. Instead, you could use: #include <iostream> #include <time> #include <SFML/System.hpp> int main(int argc, char**argv) { sf::Randomizer::SetSeed(time(NULL)); int _random = sf::Randomizer::Random(0,100); std::cout << _random << std::endl; return 0; } .. which would give you the number of seconds since 1970, and is always unique. Hope it helps, cheers!
  15. Hi, You should be able to solve this problem using the rule of cosine first and then the rule of sine. The rule of cosine can be used to get one of the angles, by knowing two sides, and then you can use the rule of sine to get the rest of them. Hope this helps and that you solve your problem. Cheers! - Rarosu