Advertisement Jump to content
  • Advertisement

john_connor

Member
  • Content Count

    8
  • Joined

  • Last visited

Community Reputation

0 Neutral

About john_connor

  • Rank
    Newbie

Personal Information

  • Interests
    Programming
  1. hi, i'm struggling with that question for a long time now. assume you have 2 programs (shader) and 2 vertex arrays to draw 2 different kind of things: 1. VAO: attributes are vec3 position, vec4 color 2. VAO: atributes are vec3 position, vec2 texturecoordinates, vec3 normals both programs use different uniforms: 1. PROGRAM: mat4 transform 2. PROGRAM: mat4 transform, several material parameters, textures, lights, ... drawcalls are the same for both ... how would you simplify that? /// general draw call struct DrawRangeElementsBaseVertex { GLenum Mode = GL_POINTS; GLuint Start = 0; GLuint End = 0; GLsizei Count = 0; GLenum Type = GL_UNSIGNED_INT; const GLvoid* Indices = nullptr; GLint BaseVertex = 0; }; /// general draw method void Draw(const DrawElementsBaseVertex & cmd) { glDrawElementsBaseVertex(cmd.Mode, cmd.Count, cmd.Type, cmd.Indices, cmd.BaseVertex); } /// (using PROGRAM 1 and VAO 1) struct CDrawableNode { /// world space transform glm::mat4 Transformation = glm::mat4(1); CMaterial Material; DrawRangeElementsBaseVertex MeshDrawCall; }; /// (using PROGRAM 2 and VAO 2) struct CDrawableGeometry { /// world space transform glm::mat4 Transformation = glm::mat4(1); /// drawcall references std::vector<DrawRangeElementsBaseVertex> DrawCalls; }; now i have 2 different for-loops for processing all the "CDrawableGeometry" and "CDrawableNode" in my scene. i'd like to do it with 1 big loop using "struct CRenderstates" somehow. has anybody some infos / links to useful sites / advices where to start with that ? somehow like: for each renderstate ... set state --> for each program/VAO ... use shader, bind program, set uniforms ----> for each object ... set program-specific uniforms, issue drawcalls
  2. john_connor

    Instancing draws nothing

    for instanced rendering, you need 3 buffer objects: (ok, the IBO is optional used with indexed rendering) 1. a vertex buffer (VBO) 2. an index buffer (IBO) ... as you had without instancing 3. an instance buffer, which contains mat4 modelmatrices of ALL object (with the same mesh) all these are put together in 1 vertex array (VAO), VBO and IBO code as before, but the difference is that your "mat4 ModelMatrix" in the shader will be an "attribute mat4" rather than a "uniform mat4" and the VAO attribute gets a glVertexAttribDivisor(attribute, 1) to make sure that for each mesh, only 1 matrix gets streamed to the shader. finally instancing doesnt work without an instanced draw call: glDrawElementsInstanced(..., instancecount); make sure your instance buffer contains at least "instancecount" matrices https://www.khronos.org/opengl/wiki/Vertex_Rendering#Instancing https://sites.google.com/site/john87connor/advanced-opengl-tutorials/tutorial-11-instanced-rendering glGenVertexArrays(1, &m_vertexarray); glGenBuffers(1, &m_vertexbuffer); glGenBuffers(1, &m_instancebuffer); glBindVertexArray(m_vertexarray); glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(Vertex), (void*)(sizeof(float) * 0)); glVertexAttribPointer(1, 4, GL_FLOAT, false, sizeof(Vertex), (void*)(sizeof(float) * 3)); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, m_instancebuffer); glVertexAttribPointer(2, 4, GL_FLOAT, false, sizeof(ModelInstance), (void*)(sizeof(float) * 0)); glVertexAttribPointer(3, 4, GL_FLOAT, false, sizeof(ModelInstance), (void*)(sizeof(float) * 4)); glVertexAttribPointer(4, 4, GL_FLOAT, false, sizeof(ModelInstance), (void*)(sizeof(float) * 8)); glVertexAttribPointer(5, 4, GL_FLOAT, false, sizeof(ModelInstance), (void*)(sizeof(float) * 12)); glBindBuffer(GL_ARRAY_BUFFER, 0); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); glEnableVertexAttribArray(3); glEnableVertexAttribArray(4); glEnableVertexAttribArray(5); // sent these attributes only once per instance to the program: glVertexAttribDivisor(2, 1); glVertexAttribDivisor(3, 1); glVertexAttribDivisor(4, 1); glVertexAttribDivisor(5, 1); glBindVertexArray(0);
  3. THANK YOU VERY MUCH !!! G-sus, without looping it works as expected 😉 am i supposed to create a "sound thread" that runs besides my app, managing all music / soundeffect-related stuff ? or do it as my ap runs (about 60 times per second) ? how do you manage musics in you game / sim / whatever ? i appreciate any advices !!
  4. how would you implement a "playlist" without queuing ?? ... the thing is: when buffer 1 is finished playing, the "sampling position" of the source jumps back to 0 seconds as it starts to play buffer 2 ... how am i supposed to set the "sampling position" to somewhere in the middle of buffer 2 then ?? my conclusion is: the AL implementation doesnt do what it is supposed to (namely giving me a 1 when buffer 1 has finished playing)
  5. #include <al.h> #include <alc.h> #include <vector> #include <string> #include <chrono> #include <iostream> #include "WAV.h" using namespace std; using namespace chrono; ALCdevice* device = nullptr; ALCcontext* context = nullptr; ALCint* attribute_list = NULL; ALuint source = 0; vector<ALuint> buffers; ALenum Format(const CWAV& wav) { if (wav.Header.NumChannels == 1) return wav.Header.BitsPerSample == 8 ? AL_FORMAT_MONO8 : AL_FORMAT_MONO16; return wav.Header.BitsPerSample == 8 ? AL_FORMAT_STEREO8 : AL_FORMAT_STEREO16; } ALuint Load(const std::string & filename) { /* load ... */ CWAV wav; if (!CWAV::Load(filename, wav)) return 0; /* create buffer */ ALuint buffer = 0; alGenBuffers(1, &buffer); alBufferData(buffer, Format(wav), wav.AudioData.data(), wav.AudioData.size(), wav.Header.SampleRate); return buffer; } bool Initialize() { device = alcOpenDevice(NULL); if (!device) return false; context = alcCreateContext(device, attribute_list); if (!context) return false; alcMakeContextCurrent(context); /* create source */ alGenSources(1, &source); /* create some buffers */ buffers.push_back(Load("track1.wav")); buffers.push_back(Load("track2.wav")); buffers.push_back(Load("track3.wav")); /* only buffers of the same format can be queued to the same source */ ALint frequency_required = 0; ALint bits_required = 0; ALint channels_required = 0; for (auto& buffer : buffers) { ALint frequency = 0; ALint bits = 0; ALint channels = 0; alGetBufferi(buffer, AL_FREQUENCY, &frequency); alGetBufferi(buffer, AL_BITS, &bits); alGetBufferi(buffer, AL_CHANNELS, &channels); /* set buffer requirements */ if (frequency_required == 0 && bits_required == 0 && channels_required == 0) { frequency_required = frequency; bits_required = bits; channels_required = channels; } /* check buffer requirements */ if (frequency != frequency_required) return false; if (bits != bits_required) return false; if (channels != channels_required) return false; } /* queue buffers to source */ alSourceQueueBuffers(source, buffers.size(), buffers.data()); /* play source */ alSourcei(source, AL_LOOPING, AL_TRUE); alSourcePlay(source); auto error = alGetError(); return error == AL_NO_ERROR; } void CleanUp() { /* detele source */ alSourcei(source, AL_BUFFER, 0); alDeleteSources(1, &source); /* delete buffers */ alDeleteBuffers(buffers.size(), buffers.data()); alcMakeContextCurrent(nullptr); if (context) alcDestroyContext(context); if (device) alcCloseDevice(device); } int Time() { static auto t_start = high_resolution_clock::now(); auto t_now = high_resolution_clock::now(); return duration_cast<duration<int>>(t_now - t_start).count(); } int main(int arc, char* argv[]) { // prepare AL if (Initialize()) { /* loop */ while (true) { /* for each second */ static int t1 = Time(); int t2 = Time(); if (t1 != t2) { t1 = t2; /* DEBUG */ ALint buffers_processed = 0; alGetSourcei(source, AL_BUFFERS_PROCESSED, &buffers_processed); cout << "buffers_processed: " << buffers_processed << endl; } } } else { cout << "failed to initialize" << endl; cin.get(); } // release AL resources CleanUp(); return 0; } WAV.cpp WAV.h above there is a test app. put some 3 wav music file beside the app, then just run it. each second it shows you AL_BUFFERS_PROCESSED in the cout console. rename the music files to track1.wav, track2.wav and track3.wav i get "buffers_processed: 0" all the time ...
  6. update: AL_BUFFERS_PROCESSED doesnt give me 1 when the source finished playing the first track ... despite whats written in the OpenAL 1.1 Specification !!! does anyone know what could be wrong ?
  7. hi, i'm trying to make a little sound class that manages all the openAL code in my app. i want to make a music playlist by queuing some buffers with musics to a source. it works. but forwarding the current "sampling position" of the source doesnt work if the first buffer has been processed. <buffer1buffer1buffer1> <buffer2buffer2buffer2> <buffer3buffer3buffer3> ... and so on ... ...........| (sampler position) as soon as the end of the first buffer is processed, and i want to skip some 3 seconds or so, it jumps back to the beginning of buffer 1 (and i dont know why) 1. how can i query the the buffers in a queued source? 2. how do i calculate the size in seconds of a buffer? 3. how do i forward the sampling position over several buffers in the queue? thanks for any advice !!!
  8. ... basically draw everything at one spot in your code (kind of centralized), NOT with "object.DrawMe();". reuse DATA whenever possible, because it doesnt make sense to have 2 times the vertices and indices of the same mesh in your buffers. minimize the state changes so that you dont call "glUseProgram(xyz);" and other API functions many times unnecessarily. if "world" contains everything you have, then "class Graphics" can be the spot where to do the job: class Graphics { void Render(const World& world); }; struct RenderState { int program; int vertexarray; bool depthtest; bool culling; void Set(/* change renderstate here */); }; struct Drawable { mat4 transformation; int material_reference; int mesh_reference; }; struct Batch { RenderState State; std::vector<Drawable> Drawables; }; /* ... workload ... */ std::vector<Batch> Batches; /* ... fill "Batches" with all you need to draw ... */ /* ... sort this array first to minimize state changes ... */ /* ... draw everything ... */ for (auto& batch : Batches) { batch.State.Set(); for (auto& drawable : Drawables) { /* set transformation */ /* set material, bind textures if necessary */ /* get drawcall parameters for mesh */ auto parameters = global_array_of_parameters[mesh_reference]; /* => to reuse meshes wherever possible !! */ /* issue draw calls */ Draw(parameters); } }
  • 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!