Exemplo n.º 1
0
/**
 * \brief Renders the internal texture if any, and all subsurfaces that are
 * drawn onto it.
 * \param renderer The renderer where to draw.
 * \param src_rect The subrectangle of the texture to draw.
 * \param dst_rect The position where to draw on the renderer.
 * \param clip_rect A portion of the renderer where to restrict the drawing.
 * \param opacity The opacity of the parent surface.
 * \param subsurfaces The subsurfaces drawn onto this texture. They will be
 * renderered recursively.
 */
void Surface::render(
    SDL_Renderer* renderer,
    const Rectangle& src_rect,
    const Rectangle& dst_rect,
    const Rectangle& clip_rect,
    uint8_t opacity,
    const std::vector<SubSurfaceNodePtr>& subsurfaces
) {

  //FIXME SDL_RenderSetClipRect is buggy for now, but should be fixed soon.
  // It means that software and hardware surface doesn't have the exact same behavior for now.
  // Uncomment the two lines using it when https://bugzilla.libsdl.org/show_bug.cgi?id=2336 will be solved.

  // Accelerate the internal software surface.
  if (internal_surface != nullptr) {

    if (internal_texture == nullptr) {
      create_texture_from_surface();
    }

    // If the software surface has changed, update the hardware texture.
    else if (
        (software_destination || !Video::is_acceleration_enabled())
         && !is_rendered) {
      SDL_UpdateTexture(
          internal_texture.get(),
          nullptr,
          internal_surface->pixels,
          internal_surface->pitch
      );
      SDL_GetSurfaceAlphaMod(internal_surface.get(), &this->opacity);
    }
  }

  const uint8_t current_opacity = std::min(this->opacity, opacity);

  // Draw the internal color as background color.
  if (internal_color != nullptr) {
    uint8_t r, g, b, a;
    internal_color->get_components(r, g, b, a);

    SDL_SetRenderDrawColor(renderer, r, g, b, std::min((uint8_t) a, current_opacity));
    //SDL_RenderSetClipRect(renderer, clip_rect.get_internal_rect());
    SDL_RenderFillRect(renderer, clip_rect.get_internal_rect());
  }

  // Draw the internal texture.
  if (internal_texture != nullptr) {
    SDL_SetTextureAlphaMod(internal_texture.get(), current_opacity);
    //SDL_RenderSetClipRect(renderer, clip_rect.get_internal_rect());

    SDL_RenderCopy(
        renderer,
        internal_texture.get(),
        src_rect.get_internal_rect(),
        dst_rect.get_internal_rect()
    );
  }

  // The surface is rendered. Now draw all subtextures.
  for (const SubSurfaceNodePtr& subsurface: subsurfaces) {

    // subsurface has to be drawn on this surface

    // Calculate absolute destination subrectangle position on screen.
    Rectangle subsurface_dst_rect(
        dst_rect.get_xy() + subsurface->dst_rect.get_xy() - src_rect.get_xy(),
        subsurface->src_rect.get_size()
    );

    // Set the intersection of the subsurface destination and this surface's clip as clipping rectangle.
    Rectangle superimposed_clip_rect;
    if (SDL_IntersectRect(subsurface_dst_rect.get_internal_rect(),
        clip_rect.get_internal_rect(),
        superimposed_clip_rect.get_internal_rect())) {

      // If there is an intersection, render the subsurface.
      subsurface->src_surface->render(
          renderer,
          subsurface->src_rect,
          subsurface_dst_rect,
          superimposed_clip_rect,
          current_opacity,
          subsurface->subsurfaces
      );
    }
  }

  is_rendered = true;
}
Exemplo n.º 2
0
void blit_block_item_sheet()
{
    GLuint block_item_64_texture = 0;
    {
        unsigned int color_tex, fb, depth_rb;
        const int xres = 1024;
        const int yres = 1024;
        const float scale = 64.0f;

        //RGBA8 2D texture, 24 bit depth texture, 256x256
        glGenTextures(1, &color_tex);
        glBindTexture(GL_TEXTURE_2D, color_tex);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        //NULL means reserve texture memory, but texels are undefined
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xres,yres, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
        //-------------------------
        glGenFramebuffersEXT(1, &fb);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
        //Attach 2D texture to this FBO
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, color_tex, 0);
        //-------------------------
        glGenRenderbuffersEXT(1, &depth_rb);
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
        glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, xres,yres);
        //-------------------------
        //Attach depth buffer to FBO
        glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
        //-------------------------
        //Does the GPU support current FBO configuration?
        GLenum status;
        status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
        switch (status)
        {
            case GL_FRAMEBUFFER_COMPLETE_EXT:
            //printf("FBO works\n");
            break;

            default:
            printf("blit_block_item_sheet: FBO error\n");
            break;
        }
        //-------------------------
        //and now you can render to GL_TEXTURE_2D
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        //-------------------------
        glViewport(0, 0, xres, yres);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0f, (float) xres, 0.0f, (float) yres, -1.0f, 1.0f);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        //-------------------------
        //glDisable(GL_TEXTURE_2D);
        glEnable(GL_TEXTURE_2D);
        GL_ASSERT(GL_BLEND, false);
        glDisable(GL_DEPTH_TEST);

        glBindTexture(GL_TEXTURE_2D, t_map::block_textures_normal);

        glBegin(GL_QUADS);
        for (int i=0; i<16; i++)
        for (int j=0; j<16; j++)
        {
            /*
                const int T = 0;
                const int B = 1;
                const int N = 2;
                const int S = 3;
                const int W = 4;
                const int E = 5;
            */

            int index = 16*j+i;
            // the NULL_CUBE is reserved at 255 (so that it fits in a packet)
            // must skip it
            if (!isValid((CubeType)index)) continue;

            int s1 = get_cube_side_texture((CubeType)index, 0); //T
            int s2 = get_cube_side_texture((CubeType)index, 2); //N
            int s3 = get_cube_side_texture((CubeType)index, 4); //W

            draw_iso_cube(i*scale, j*scale, scale, s1,s2,s3);
        }
        glEnd();

        block_item_64_surface = create_surface_from_nothing(xres, yres);

        SDL_LockSurface(block_item_64_surface);
        GLenum format = get_texture_format(block_item_64_surface);

        //glReadPixels(0, 0, xres, yres, GL_RGBA, GL_UNSIGNED_BYTE, (void*) block_item_64_surface->pixels);
        glReadPixels(0, 0, xres, yres, format, GL_UNSIGNED_BYTE, (void*) block_item_64_surface->pixels);

        SDL_UnlockSurface(block_item_64_surface);

        save_surface_to_png(block_item_64_surface, SCREENSHOT_PATH "fbo_test_64.png");

        //Delete resources
        glDeleteTextures(1, &color_tex);
        glDeleteRenderbuffersEXT(1, &depth_rb);
        //Bind 0, which means render to back buffer, as a result, fb is unbound
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
        glDeleteFramebuffersEXT(1, &fb);

        //http://stackoverflow.com/questions/5102277/resizing-an-image-using-opengl
        // setup another framebuffer here
        // bind the 64 pixel texture
        // draw to a 256x256 framebuffer
        // save surface to png again

        create_texture_from_surface(block_item_64_surface, &block_item_64_texture, GL_NEAREST);
        //create_texture_from_surface(block_item_64_surface, &block_item_64_texture, GL_LINEAR);
        GS_ASSERT_ABORT(block_item_64_texture != 0);
        SDL_FreeSurface(block_item_64_surface);
    }

    {
        unsigned int color_tex, fb, depth_rb;
        const int xres = 256;
        const int yres = 256;
        //const float scale = 16.0;

        //RGBA8 2D texture, 24 bit depth texture, 256x256
        glGenTextures(1, &color_tex);
        glBindTexture(GL_TEXTURE_2D, color_tex);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        //NULL means reserve texture memory, but texels are undefined
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xres,yres, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
        //-------------------------
        glGenFramebuffersEXT(1, &fb);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
        //Attach 2D texture to this FBO
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, color_tex, 0);
        //-------------------------
        glGenRenderbuffersEXT(1, &depth_rb);
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
        glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, xres,yres);
        //-------------------------
        //Attach depth buffer to FBO
        glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
        //-------------------------
        //Does the GPU support current FBO configuration?
        GLenum status;
        status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
        switch (status)
        {
            case GL_FRAMEBUFFER_COMPLETE_EXT:
            //printf("FBO works\n");
            break;

            default:
            printf("blit_block_item_sheet: FBO error\n");
            break;
        }
        //-------------------------
        //and now you can render to GL_TEXTURE_2D
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        //-------------------------
        glViewport(0, 0, xres, yres);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0f, (float) xres, 0.0f, (float) yres, -1.0f, 1.0f);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        //-------------------------
        //glDisable(GL_TEXTURE_2D);
        glEnable(GL_TEXTURE_2D);
        GL_ASSERT(GL_BLEND, false);
        glDisable(GL_DEPTH_TEST);

        //glBindTexture(GL_TEXTURE_2D, t_map::block_textures_normal);

        //glBegin(GL_QUADS);
        //for (int i=0; i<16; i++)
        //for (int j=0; j<16; j++)
        //{
            ///*
                //const int T = 0;
                //const int B = 1;
                //const int N = 2;
                //const int S = 3;
                //const int W = 4;
                //const int E = 5;
            //*/

            //int index = 16*j+i;
            //int s1 = get_cube_side_texture(index, 0); //T
            //int s2 = get_cube_side_texture(index, 2); //N
            //int s3 = get_cube_side_texture(index, 4); //W

            //draw_iso_cube(i*scale, j*scale, scale, s1,s2,s3);
        //}
        //glEnd();

        //glBegin(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, block_item_64_texture);
        draw_bound_texture(0.0f, 0.0f, xres, yres);
        //glDisable(GL_TEXTURE_2D);

        block_item_16_surface = create_surface_from_nothing(xres, yres);
        SDL_LockSurface(block_item_16_surface);
        GLenum format = get_texture_format(block_item_16_surface);
        //glReadPixels(0, 0, xres, yres, GL_RGBA, GL_UNSIGNED_BYTE, (void*) block_item_16_surface->pixels);
        glReadPixels(0, 0, xres, yres, format, GL_UNSIGNED_BYTE, (void*) block_item_16_surface->pixels);

        SDL_UnlockSurface(block_item_16_surface);

        save_surface_to_png(block_item_16_surface, SCREENSHOT_PATH "fbo_test_16.png");

        //Delete resources
        glDeleteTextures(1, &color_tex);
        glDeleteRenderbuffersEXT(1, &depth_rb);
        //Bind 0, which means render to back buffer, as a result, fb is unbound
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
        glDeleteFramebuffersEXT(1, &fb);
        SDL_FreeSurface(block_item_16_surface);
    }

    glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
    glViewport (0, 0, _xres, _yres);
}
Exemplo n.º 3
0
/**
 * \brief Renders the internal texture if any, and all subsurfaces that are
 * drawn onto it.
 * \param renderer The renderer where to draw.
 * \param src_rect The subrectangle of the texture to draw.
 * \param dst_xy The position where to draw on the renderer.
 * The width and height of this rectangle are ignored.
 * \param clip_rect A portion of the renderer where to restrict the drawing.
 * \param opacity The opacity of the parent surface.
 * \param subsurfaces The subsurfaces drawn onto this texture. They will be
 * renderered recursively.
 */
void Surface::render(
    SDL_Renderer* renderer,
    const Rectangle& src_rect,
    const Rectangle& dst_xy,
    const Rectangle& clip_rect,
    uint8_t opacity,
    const std::vector<SubSurfaceNode*>& subsurfaces) {

  const uint8_t current_opacity = std::min(internal_opacity, opacity);

  // Accelerate the internal software surface.
  if (internal_surface != NULL) {

    if (internal_texture == NULL) {
      create_texture_from_surface();
    }

    // If the software surface has changed, update the hardware texture.
    else if (
        (software_destination || !Video::is_acceleration_enabled())
         && !is_rendered) {
      convert_software_surface();
      SDL_UpdateTexture(
          internal_texture,
          NULL,
          internal_surface->pixels,
          internal_surface->pitch
      );
      SDL_GetSurfaceAlphaMod(internal_surface, &internal_opacity);
    }
  }

  // Draw the internal color as background color.
  if (internal_color != NULL) {
    int r, g, b, a;
    internal_color->get_components(r, g, b, a);

    SDL_SetRenderDrawColor(renderer, r, g, b, std::min((uint8_t) a, current_opacity));
    //SDL_RenderSetClipRect(renderer, clip_rect.get_internal_rect());
    SDL_RenderFillRect(renderer, clip_rect.get_internal_rect());
  }

  // Draw the internal texture.
  if (internal_texture != NULL) {
    SDL_SetTextureAlphaMod(internal_texture, current_opacity);
    //SDL_RenderSetClipRect(renderer, clip_rect.get_internal_rect());

    SDL_RenderCopy(
        renderer,
        internal_texture,
        src_rect.get_internal_rect(),
        dst_xy.get_internal_rect()
    );
  }

  // The surface is renderered. Now draw all subtextures.
  std::vector<SubSurfaceNode*>::const_iterator it;
  const std::vector<SubSurfaceNode*>::const_iterator end = subsurfaces.end();
  for (it = subsurfaces.begin(); it != end; ++it) {
    SubSurfaceNode* subsurface = *it;

    // subsurface has to be drawn on this surface

    // Calculate absolute destination subrectangle position on screen.
    Rectangle subsurface_dst_rect(
        dst_xy.get_x() + subsurface->dst_rect.get_x() - src_rect.get_x(),
        dst_xy.get_y() + subsurface->dst_rect.get_y() - src_rect.get_y(),
        subsurface->src_rect.get_width(),
        subsurface->src_rect.get_height()
    );

    // Set the intersection of the subsurface destination and this surface's clip as clipping rectangle.
    Rectangle superimposed_clip_rect;
    if (SDL_IntersectRect(subsurface_dst_rect.get_internal_rect(),
        clip_rect.get_internal_rect(),
        superimposed_clip_rect.get_internal_rect())) {

      // If there is an intersection, render the subsurface.
      subsurface->src_surface->render(
          renderer,
          subsurface->src_rect,
          subsurface_dst_rect,
          superimposed_clip_rect,
          current_opacity,
          subsurface->subsurfaces
      );
    }
  }

  is_rendered = true;
}