Jump to content

NightQuest

Members
  • Posts

    32
  • Joined

  • Last visited

Posts posted by NightQuest

  1. Forgive me if I'm wrong, but I think your problem may be the const

    const char* pixelBuf = new char[tex->GetMipmapSize(0)];
    tex->GetPixels(pixelBuf);
    

    When I did this, I had to cast it

    GLubyte* tPixels = new GLubyte[tex->GetMipmapSize(0)];
    tex->GetPixels(reinterpret_cast<const char*>(tPixels));
    

     

    I have no idea why it's passed as a const char* since it's obviously modified; if anything, it should be passed as a char* const.

  2. In le 2 it only took 1 line of code to get fullscreen the last parameter being "32"..

     

    Same in the new ones, it's only the last parameter that matters, but it's Window::FullScreen instead of 32.

    The rest of the code is just fluff.

     

    You may want to get the system width/height for that window, actually. I don't believe LE has a method to determine the current monitor width/height (only supported ones), though so you'd have to rely on native calls.

     

    On Windows (I don't know how on *nix):

    unsigned int width = GetSystemMetrics(SM_CXSCREEN);
    unsigned int height = GetSystemMetrics(SM_CYSCREEN);
    

  3. in C++:

    unsigned int windowStyle = Window::Titlebar | Window::Center;
    if( stoi(System::GetProperty("fullscreen")) )
       windowStyle = Window::FullScreen;
    
    unsigned int width = stoi(System::GetProperty("width", "1920"));
    unsigned int height = stoi(System::GetProperty("height", "1080"));
    
    Window* window = Leadwerks::Window::Create("Test", 0, 0, width, height, windowStyle );
    

  4. Thanks to this, something like this should work

     

    EDIT: I installed XUbuntu 14.04 on dual-boot to test this, below is the working version

    bool isActiveWindow(Leadwerks::Window* window)

    {

    if( window == nullptr )

    return false;

     

    #if defined(__linux__) && !defined(__ANDROID__)

    ::Window root = 0L;

    ::Window active = 0L;

    Atom _NET_ACTIVE_WINDOW = XInternAtom(window->display, "_NET_ACTIVE_WINDOW", False);

    Atom actual_type;

    int actual_format;

    unsigned long count, bytesAfter;

    unsigned char* properties = NULL;

     

    root = DefaultRootWindow(window->display);

    if( XGetWindowProperty(window->display, root, _NET_ACTIVE_WINDOW, 0L, sizeof(::Window), False, XA_WINDOW, &actual_type, &actual_format, &count, &bytesAfter, &properties) == Success )

    {

    active = *reinterpret_cast<::Window*>(properties);

    XFree(properties);

    }

     

    return (window->window == active);

    #else

    return window->Active();

    #endif

    }

  5. We have Window::setLayout which is awesome for resizing.. but what if we want borderless window? smile.png

     

    Right now, I'm using this platform-specific code for that:

    if( window->KeyHit(Key::F11) )

    {

    int screenWidth = GetSystemMetrics(SM_CXSCREEN);

    int screenHeight = GetSystemMetrics(SM_CYSCREEN);

     

    if( fullscreen )

    {

    long style = reinterpret_cast<long>(window->GetUserData());

    SetWindowLongPtr(window->hwnd, GWL_STYLE, style);

     

    int width = stoi(System::GetProperty("width", "1280"));

    int height = stoi(System::GetProperty("height", "720"));

     

    window->SetLayout((screenWidth - width) / 2, (screenHeight - height) / 2, width, height);

    }

    else

    {

    long style = GetWindowLongPtr(window->hwnd, GWL_STYLE);

    window->SetUserData(reinterpret_cast<void*>(style));

    SetWindowLongPtr(window->hwnd, GWL_STYLE, style & ~(WS_BORDER | WS_OVERLAPPEDWINDOW));

    window->SetLayout(0, 0, screenWidth, screenHeight);

    }

    fullscreen = !fullscreen;

    }

     

     

    This would allow us to simply do:

     

    if( window->KeyHit(Key::F11) )

    {

    fullscreen = !fullscreen;

     

    int width = fullscreen ? GetSystemMetrics(SM_CXSCREEN) : stoi(System::GetProperty("width", "1280"));

    int height = fullscreen ? GetSystemMetrics(SM_CYSCREEN) : stoi(System::GetProperty("height", "720"));

     

    int style = Window::Center;

    if( fullscreen )

    style &= ~Window::Titlebar;

    else

    style |= Window::Titlebar;

     

    window->setStyle(style);

    window->setLayout(0, 0, width, height);

    }

     

     

    And maybe we could get a

    Vec2 System::GetCurrentMonitorResolution();
    

     

    or something to retrieve the current monitors display resolution?

    While I don't mind the Win32API, I'd like to be able to easily do these things on both platforms.

     

    GTK+ has gtk-window-set-decorated, and X11 has DefaultScreenOfDisplay.

    • Upvote 1
  6. I was able to get it to take the top left at the correct scale by passing the final size to buffer, but not the texture. However, It looks like World::Render() always renders at 0,0

     

    This caused me to look at camera::setViewport(), but I cannot seem to use it correctly.

     

    Has anyone used this before?

     

    bool ScreenshotHighRes(Camera* camera, const std::string& filename, GLint scale)
    {
       if( scale <= 1 )
           return Context::GetCurrent()->Screenshot(filename);
    
       bool ret = false;
    
       GLint    tileWidth = Context::GetCurrent()->GetWidth(),
               tileHeight = Context::GetCurrent()->GetHeight();
       GLint    finalWidth = tileWidth * scale,
               finalHeight = tileHeight * scale;
    
       Buffer* oBuffer = Buffer::GetCurrent();
       Buffer* buffer = Buffer::Create(finalWidth, finalHeight);
       Texture* tex = Texture::Create(tileWidth, tileHeight);
       buffer->SetColorTexture(tex);
       Buffer::SetCurrent(buffer);
    
       GLuint texSize = tex->GetMipmapSize(0);
    
       GLubyte* tPixels = new GLubyte[texSize];
       memset(tPixels, 0, texSize);
    
       GLubyte* pixels = new GLubyte[(tileWidth * 3) * tileHeight];
       memset(pixels, 0, (tileWidth * 3) * tileHeight);
    
       GLuint rowLength = tileWidth * 3;
       GLubyte* line = new GLubyte[rowLength];
       memset(line, 0, rowLength);
    
       GLuint count = 0;
       for( GLint y = 0; y < scale; ++y )
       {
           for( GLint x = 0; x < scale; ++x )
           {
               camera->SetViewport((x - 1)*tileWidth, (y - 1)*tileHeight, tileWidth, tileHeight);
    
               World::GetCurrent()->Render();
    
               tex->GetPixels(reinterpret_cast<const char*>(tPixels));
    
               // BGRA -> RGB
               for( GLuint p = 0, t = 0; t < texSize; t += 4, p += 3 )
               {
                   pixels[p] = tPixels[t + 2];
                   pixels[p + 1] = tPixels[t + 1];
                   pixels[p + 2] = tPixels[t];
               }
    
               // Flip image vertically
               for( GLint row = 0; row < tileHeight / 2; row++ )
               {
                   memcpy(line, pixels + (row * rowLength), rowLength);
                   memcpy(pixels + (row * rowLength), pixels + ((tileHeight - row - 1) * rowLength), rowLength);
                   memcpy(pixels + ((tileHeight - row - 1) * rowLength), line, rowLength);
               }
    
               // Write TGA
               TGAHeader tgah = { 0 };
               tgah.ImageType = 2;
               tgah.ImageWidth = tileWidth;
               tgah.ImageHeight = tileHeight;
               tgah.PixelDepth = 24;
               Stream* file = FileSystem::WriteFile(filename + "_" + to_string(x) + "_" + to_string(y) + ".tga");
               if( file )
               {
                   file->Write(&tgah, sizeof(TGAHeader));
                   file->Write(pixels, (tileWidth * 3) * tileHeight);
                   file->Release();
                   count++;
               }
           }
       }
    
       if( count == scale )
           ret = true;
    
       delete[] tPixels;
       delete[] pixels;
       delete[] line;
    
       Buffer::SetCurrent(oBuffer);
       tex->Release();
       buffer->Release();
    
       return ret;
    }

  7. I don't see why your messing with camera projection and stitching ( unless you want to make panoramas ofcourse )

     

    Have a look here;

    http://www.43rumors.com/ft5-e-m5-successor-has-sensor-shift-to-create-up-to-40-megapixel-images-on-the-fly/

     

    Grabbing 9 screen shots shifted like in the above link should take 0.15s with a bit of extra time for post processing

     

    But maybe I'm missing something ?

     

    That's actually exactly what I'm trying to do. This is a pretty foreign thing to me, so I'm sure I'm on the wrong track.. But from what I can tell I need to adjust the viewport while preserving the camera's location and angle as to not mess with parallax.

     

    Before this, I had tried to use gluPickMatrix but that didn't produce any effect at all; I assumed this was because it's deprecated so I gave this a shot.. Which also seemingly did nothing.. :/

     

    Sorry for typos, wrote this on my phone.

  8. From what I can tell, this should work (and is far faster - it happens within a second) - but it looks like World::Render() might be interfering with the matrix being set - is there a way to force it to use mine?

     

    bool ScreenshotHighRes(const std::string& filename, GLint scale)
    {
       if( scale <= 1 )
           return Context::GetCurrent()->Screenshot(filename);
    
       bool ret = false;
    
       GLint    tileWidth = Context::GetCurrent()->GetWidth(),
               tileHeight = Context::GetCurrent()->GetHeight();
       GLint    finalWidth = tileWidth * scale,
               finalHeight = tileHeight * scale;
    
       Buffer* oBuffer = Buffer::GetCurrent();
       Buffer* buffer = Buffer::Create(tileWidth, tileHeight);
       Texture* tex = Texture::Create(tileWidth, tileHeight);
       buffer->SetColorTexture(tex);
       Buffer::SetCurrent(buffer);
    
       GLuint texSize = tex->GetMipmapSize(0);
    
       GLubyte* tPixels = new GLubyte[texSize];
       memset(tPixels, 0, texSize);
    
       GLubyte* pixels = new GLubyte[(tileWidth * 3) * tileHeight];
       memset(pixels, 0, (tileWidth * 3) * tileHeight);
    
       GLuint rowLength = tileWidth * 3;
       GLubyte* line = new GLubyte[rowLength];
       memset(line, 0, rowLength);
    
    
       GLfloat pm[16];
       glGetFloatv(GL_PROJECTION_MATRIX, &pm[0]);
    
       glMatrixMode(GL_PROJECTION);
       glPushMatrix();
    
       for( GLint y = 0; y < scale; ++y )
       {
           for( GLint x = 0; x < scale; ++x )
           {
               buffer->Clear();
    
               // Zoom in to the tile
               glLoadIdentity();
               glTranslatef(tileWidth - 2.0*x - 1, tileHeight - 2.0*y - 1, 0.0);
               glScalef(tileWidth, tileHeight, 1);
               glMultMatrixf(&pm[0]);
    
               World::GetCurrent()->Render();
    
               tex->GetPixels(reinterpret_cast<const char*>(tPixels));
    
               // BGRA -> RGB
               for( GLuint p = 0, t = 0; t < texSize; t += 4, p += 3 )
               {
                   pixels[p] = tPixels[t + 2];
                   pixels[p + 1] = tPixels[t + 1];
                   pixels[p + 2] = tPixels[t];
               }
    
               // Flip image vertically
               for( GLint row = 0; row < tileHeight / 2; row++ )
               {
                   memcpy(line, pixels + (row * rowLength), rowLength);
                   memcpy(pixels + (row * rowLength), pixels + ((tileHeight - row - 1) * rowLength), rowLength);
                   memcpy(pixels + ((tileHeight - row - 1) * rowLength), line, rowLength);
               }
    
               // Write TGA
               TGAHeader tgah = { 0 };
               tgah.ImageType = 2;
               tgah.ImageWidth = tileWidth;
               tgah.ImageHeight = tileHeight;
               tgah.PixelDepth = 24;
               Stream* file = FileSystem::WriteFile(filename + "_" + to_string(x) + "_" + to_string(y) + ".tga");
               if( file )
               {
                   file->Write(&tgah, sizeof(TGAHeader));
                   file->Write(pixels, (tileWidth * 3) * tileHeight);
                   file->Release();
               }
           }
       }
       glPopMatrix();
    
    
       delete[] tPixels;
       delete[] pixels;
       delete[] line;
    
       Buffer::SetCurrent(oBuffer);
       buffer->GetColorTexture()->Release();
       buffer->Release();
    
       return ret;
    }
    

  9. 8k is pretty big man!

    It is, but my aim was to low-end proof it - by stitching it together like that, someone with a low-end machine would still be able to get a 8K screen if they wanted to. smile.png

     

    You could send a matrix to the shader that makes the camera render only a part of its view...but that would be tricky and I am not 100% sure it would work.

    That's essentially what I was going for - taking the view and chopping it up into, say 3x3 screenshots - then using a smiliar method as above to move them all into a single image.

     

    I may have to just settle for this, as it works pretty good - it's just limiting on some machines.

    • Upvote 1
  10. One of my favorite features in some newer titles (I'm looking at you, Elite Dangerous) has been the ability to render screenshots that are well beyond the users screen resolution.

     

    The built in Context::Screenshot does not support this, so I made one that did.

     

    Sadly, I can only seem to squeeze 8K out of it, which takes roughly ~10 seconds to complete.

     

    I figured the fix for this would be to take a series of screenshots, and stitch them together prior to saving.

     

    I am however, completely lost. I think I'd have to move the camera and zoom in, and yet somehow preserve parallax.

     

    Any tips on how to proceed?

     

    #pragma pack(push, 1)
    struct TGAHeader
    {
       BYTE IDLength;
       BYTE ColormapType;
       BYTE ImageType;
       WORD ColorMapStart;
       WORD ColorMapLength;
       BYTE ColorMapDepth;
       WORD XOrigin;
       WORD YOrigin;
       WORD ImageWidth;
       WORD ImageHeight;
       BYTE PixelDepth;
       BYTE ImageDescriptor;
    };
    #pragma pack(pop)
    
    bool App::ScreenshotHighRes(const std::string& filename, const unsigned int scale)
    {
       Buffer* current = Buffer::GetCurrent();
       float par = (float)current->GetWidth() / (float)current->GetHeight();
       return ScreenshotHighRes(filename, (current->GetHeight() * scale) * par, current->GetHeight() * scale);
    }
    
    bool App::ScreenshotHighRes(const std::string& filename, const unsigned int width, const unsigned int height)
    {
       bool ret = false;
    
       // Set our new buffer and render
       Buffer* oldbuf = Buffer::GetCurrent();
       Buffer* buffer = Buffer::Create(width, height);
       buffer->SetColorTexture(Texture::Create(width, height));
       Buffer::SetCurrent(buffer);
       World::GetCurrent()->Render();
    
       // Capture the texture
       Texture* tex = buffer->GetColorTexture();
       GLuint texSize = tex->GetMipmapSize(0);
       GLuint texWidth = tex->GetWidth();
       GLuint texHeight = tex->GetHeight();
       GLubyte* pixels = new GLubyte[texSize];
       memset(pixels, 0, texSize);
       tex->GetPixels(reinterpret_cast<const char*>(pixels));
    
       // Minor cleanup
       Buffer::SetCurrent(oldbuf);
       tex->Release();
       buffer->Release();
    
       // BGRA -> RGB
       GLubyte* tmp = new GLubyte[(texWidth * 3) * texHeight];
       for( GLuint y = 0, x = 0; x < texSize; x += 4, y += 3 )
       {
           tmp[y] = pixels[x + 2];
           tmp[y + 1] = pixels[x + 1];
           tmp[y + 2] = pixels[x];
       }
       delete[] pixels;
       pixels = tmp;
    
       // Flip image vertically
       GLuint rowLength = texWidth * 3;
       GLubyte* line = new GLubyte[rowLength];
       for( GLuint row = 0; row < texHeight / 2; row++ )
       {
           memcpy(line, pixels + (row * rowLength), rowLength);
           memcpy(pixels + (row * rowLength), pixels + ((texHeight - row - 1) * rowLength), rowLength);
           memcpy(pixels + ((texHeight - row - 1) * rowLength), line, rowLength);
       }
       delete[] line;
    
       // Write TGA
       TGAHeader tgah = { 0 };
       tgah.ImageType = 2;
       tgah.ImageWidth = texWidth;
       tgah.ImageHeight = texHeight;
       tgah.PixelDepth = 24;
       Stream* file = FileSystem::WriteFile(filename);
       if( file )
       {
           file->Write(&tgah, sizeof(TGAHeader));
           file->Write(pixels, (texWidth * 3) * texHeight);
           file->Release();
           ret = true;
       }
    
       delete[] pixels;
    
       return ret;
    }
    

     

    EDIT:

    It looks like I'll need to modify the Cameras projection matrix for this - is that exposed?

  11. I tried looking for a function to create a plane, but couldn't find one.

    I threw this together in its place, which may be for the better since I needed a slightly weird kind of plane:

    Leadwerks::Model* CreatePlane(unsigned int accross, unsigned int down)
    {
       float halfAcross = ((float)accross) / 2;
       unsigned int rows = down + accross - 1;
       float halfRows = ((float)rows) / 2;
       unsigned int total = ((rows - 1) * accross) + 1;
    
       Leadwerks::Model* model = Leadwerks::Model::Create();
       Leadwerks::Surface* surface = model->AddSurface();
    
       float Z = 1.f;
       for( unsigned int row = 0; row < rows; row++ )
       {
           float X;
           if( row > 0 )
           {
               X = -1.f + ((1.f / halfAcross) / 2.f);
               for( unsigned int column = 0; column < accross - 1; column++ )
               {
                   surface->AddVertex(Vec3(X, 0.f, Z));
                   X += (1.f / halfAcross);
               }
               Z -= (1.f / halfRows);
               row++;
           }
    
           X = -1.f;
           for( unsigned int column = 0; column < accross; column++ )
           {
               surface->AddVertex(Vec3(X, 0.f, Z));
               X += (1.f / halfAcross);
           }
           Z -= (1.f / halfRows);
       }
       for( unsigned int done = 0; done < total; )
       {
           for( unsigned int column = 0; column < accross; column++, done++ )
           {
               if( column < accross - 1 && done < (total - 1) - accross) // Top
                   surface->AddTriangle(done, done + 1, done + accross);
    
               if( column > 0 && done > rows - 1 ) // Right
                   surface->AddTriangle(done, done - accross, done - rows);
    
               if( column < accross - 1 && done > rows - 1 ) // Bottom
                   surface->AddTriangle(done, done - (accross - 1), done + 1);
    
               if( column < accross - 1 && done > rows - 1 ) // Left
                   surface->AddTriangle(done, done - rows, done - (accross - 1));
           }
           done += (accross - 1);
       }
    
       surface->UpdateAABB();
       model->UpdateAABB(Entity::LocalAABB | Entity::GlobalAABB);
       return model;
    }
    

     

    It works pretty well,

    Model* plane = CreatePlane(9, 9);
    plane->SetColor(0.2f, 0.2f, 0.2f);
    plane->SetPosition(0, 10, 5);
    plane->SetScale(25.f);
    plane->SetMaterial(Material::Load("Materials/Concrete/concrete_clean.mat"));
    

     

    .. except for that last line. The material, for whatever reason, doesn't get applied.

     

    However, the (relatively) same code works fine for a Box:

    Model* box = Model::Box(9, 9, 9);
    box->SetColor(0.2f, 0.2f, 0.2f);
    box->SetPosition(0, 15, 5);
    box->SetScale(1.f);
    box->SetMaterial(Material::Load("Materials/Concrete/concrete_clean.mat"));
    

     

    Any ideas? :/

    post-103-0-18283100-1424816293_thumb.png

  12. I love the engine, and admire Josh for all the work he's done on it so far. It's pretty amazing to see how it and the company have come so far. But Josh needs to remember what got him here.

     

    With barely any games finished (if any?), no professional demos done, barely any features beyond graphical capabilities that other engines do not possess.. I'm honestly left asking myself, if I had $1,000 in my hand when sales opened, and I hadn't bought LE2, would I purchase LE3 with all these faults? Especially when I see the community turning on its founder? No, probably not. I'd like go look at other game engines that from a new-comers viewpoint, would have a better, and less stressful future. When I initially was looking at new engines, what lead me here was the graphical capabilities of the engine, the community, and honestly the similarity between the Editor and FarCry's editor.

     

    I personally was not expecting the price to be anymore than double what the price of LE2 was. Especially when from a customer standpoint, there's very few new features.

     

    One option I've seen other engine use in the past for a pricing model is having an Indie license, and a Pro license - entirely based on annual revenue and not eliminating features based on the version. This would allow a cheaper version of the product, while still keeping the current pricing model for those that need it.

×
×
  • Create New...