How improve quality of shadows?

Results 1 to 11 of 11
  1. #1
    Apprentice Lerath is offline
    MemberRank
    Aug 2015 Join Date
    14Posts

    Support How improve quality of shadows?

    Hello again,

    in this time im want talk about mu online shadows, as everybody know it's very ugly element of this game, but maybe we can improve it's?

    im start from idea that better use transparent shadows (as in atlants), example:


    for get analogy effect in any location im decompile function which calculate and render shadows of game object:
    Code:
    void CMUModelObjectPrototype::RenderShadow(MUModelObject* this_, int unk_0, int unk_1, int part_from_index, int part_to_index, int scale) {
        if (this_->m_FileInfo.PartPoolSize <= 0) {
            return;
        }
        
        if (g_GameWorld_Scene_Current != 7) { // now we have 0.2f transparent in any location
            GameGL_EnableBlend(false);
            glColor4f(0.0f, 0.0f, 0.0f, 0.2f);
        }
    
        GameGL_DisableTexture2d(false);
        GameGL_DisableDepthMask();
    
        glPushMatrix();
    
        float width = 2000.0f;
        float height = 4000.0f;
    
        if (g_GameWorld_Scene_Current == 30/*castle siege*/) {
            width = 2500.0f;
            height = 4000.0f;
        }
    
        int part_index_start = 0;
        if (part_from_index != -1) {
            part_index_start = part_from_index;
        }
    
        int part_index_end = this_->m_FileInfo.PartPoolSize;
        if (part_to_index != -1) {
            part_index_end = part_to_index;
        }
        
        for (int i = part_index_start; i < part_index_end; i++) {
            if (i == unk_1) {
                continue;
            }
            
            MUModelPart* part_object = &this_->m_PartPool[i];
    
            if (part_object->TrianglePoolSize <= 0 || part_object->Index == unk_0) {
                continue;
            }
    
    
            glBegin(GL_TRIANGLES);
            for (int j = 0; j < part_object->TrianglePoolSize; j++) {
                MUModelPartTriangle* triangle_object = &part_object->TrianglePool[j];
                
                for (int k = 0; k < triangle_object->field_0; k++) {
                    MUVector3f vertex;
    
                    int triangle_world_index = triangle_object->PositionPoolIndex[k];
                    int world_vertex_memory_offset = 0x7702578 + (180000 * i) + (triangle_world_index * 12); // like array [100][150]
                    MUVector3f* world_vertex = &*(MUVector3f*)world_vertex_memory_offset;
    
    
                    vertex.X = world_vertex->X - this_->field_6C.X;
                    vertex.Y = world_vertex->Y - this_->field_6C.Y;
                    vertex.Z = world_vertex->Z - this_->field_6C.Z;
    
                    vertex.X = (vertex.X + width) * vertex.Z / (vertex.Z - height) + vertex.X;
                    
                    vertex.X += this_->field_6C.X;
                    vertex.Y += this_->field_6C.Y;
                    vertex.Z = 5.0f + this_->field_6C.Z + scale;
                    
                    glVertex3fv((GLfloat*)&vertex);
                }
            }
            glEnd();
        }
    
        glPopMatrix();
        glDisable(GL_BLEND);  
    
        GameGL_EnableDepthMask();
    }
    and it's work fine, shadows now transparent in any location, but im detect funny problems:
    1. when triangles get collision shadow work incorrect (with this need help)


    2. shadow does not display weapon / items / wings (it's im understand how fix, np)



    my thoughts about solution for problem №1:

    a) merge triangles in group and render single object after (but don't know how can make this, found one idea in google, but method for new version of opengl)

    b) add black texture which must hide triangles (dont know will help or no, if someone have experience - please reply)

    so, im have null experience with 3d graphic and opengl, but maybe u know how we can improve it's without changing the basic principles (creation shadow map is not good idea, many for recode) and can help with this?

    @laudaicat
    what do you think about this?
    Last edited by Lerath; 01-12-15 at 07:16 AM.


  2. #2
    Member laudaicat is offline
    MemberRank
    Oct 2008 Join Date
    86Posts

    Re: How improve quality of shadows?

    1. About triangle shadow collision: use stencil buffer to fix that, when draw shadow: clear stencil to 0, draw shadow to set stencil to 1, after that, fill shadow color only on stencil = 1

    2. About shadow character: webzen use shadow player bmd ( player/shadow.bmd - i don't remember exactly ), with simplest model, is not full player model include weapon, wing...

    You can increase shadow quality, but cpu increase too. Best way is shader, but it hard to use on mu engine.

  3. #3

    Re: How improve quality of shadows?

    You should improve it just like monster's shadows work.
    Its usual very similar, but as you see Monsters shadow show also weapons too (atleast Boss monsters as i seen)
    Then you make it little transparent and to make it even hotter try to add detail texture on the shadow for example:

    Simple example with textures



    so what u should try to do is on shadow effect to put an transparent texture with small like detailed effects extra that will show instead of pure black if you get what i mean :) try it.

  4. #4
    Apprentice Lerath is offline
    MemberRank
    Aug 2015 Join Date
    14Posts

    Re: How improve quality of shadows?

    Okay, im get time and start lern guides about stencil buffers in opengl, and result is good:


    problem with collision is closed, now im continue lern and try make blur.

    thank to @laudaicat for idea

    steps for draw solid shadow:
    1. render ground
    1.1. render ground to stencil buffer
    1.2. render ground to main buffer
    2. render units
    2.1. render units shadow from stencil buffer

    i will post more information when finish improving.
    @KarLi ty for good idea, but im cant understand what mean ur screenshots, im talk about texture to shadow object, but u show texture on ground

  5. #5

    Re: How improve quality of shadows?

    Quote Originally Posted by Lerath View Post
    Okay, im get time and start lern guides about stencil buffers in opengl, and result is good:


    problem with collision is closed, now im continue lern and try make blur.

    thank to @laudaicat for idea

    steps for draw solid shadow:
    1. render ground
    1.1. render ground to stencil buffer
    1.2. render ground to main buffer
    2. render units
    2.1. render units shadow from stencil buffer

    i will post more information when finish improving.
    @KarLi ty for good idea, but im cant understand what mean ur screenshots, im talk about texture to shadow object, but u show texture on ground
    I was talking texture on general mate it was only an example that u can put DETAIL on the shadow texture

  6. #6
    Apprentice Lerath is offline
    MemberRank
    Aug 2015 Join Date
    14Posts

    Re: How improve quality of shadows?

    so, im not get approval from heaven for continue it's and stop with this result:


    shadows look really better, but maked only 2 items: transparent, solid rendering of shadow.

    im not will publish full source code bcz it's not have reason (many research for other main.exe), only 2 functions for understand concept:

    Code:
    // global static function
    void GameRenderer_RenderGround(int mode) {
        glEnable(GL_STENCIL_TEST);
        glClear(GL_STENCIL_BUFFER_BIT);
         
        // disable draw in other buffers, will draw only in stencil
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
        glDepthMask(GL_FALSE);
        
        // setup stencil buffer
        glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
    
        imp_GameRenderer_RenderGround(mode); // render ground to stencil
    
        // continue draw stencil only with "1" id & save buffer for continue
        glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
    
        // restore other buffers
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glDepthMask(GL_TRUE);
        
        glDisable(GL_STENCIL_TEST);
    
        imp_GameRenderer_RenderGround(mode); // render ground to normal
    }
    
    // class method
    void CResourceExtension::CreateObjectShadow(MUModelObject* this_, int unk_0, int unk_1, int part_from_index, int part_to_index, int scale) {
        if (this_->m_FileInfo.PartPoolSize <= 0) {
            return;
        }
    
    
        if (g_GameWorld_Scene_Current != 7) { // we check world bcz atlans already enable blend
            GameGL_EnableBlend(false);
        }
    
    
        glColor4f(0.0f, 0.0f, 0.0f, 0.3f); // 30% opacity for shadow
    
    
        GameGL_DisableTexture2d(false);
        GameGL_DisableDepthMask();
    
    
        glPushMatrix();
        
        // enable stencil and continue draw
        glEnable(GL_STENCIL_TEST);
        glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
    
    
        float width = 2000.0f;
        float height = 4000.0f;
    
    
        if (g_GameWorld_Scene_Current == 30/*castle siege*/) {
            width = 2500.0f;
            height = 4000.0f;
        }
    
    
        int part_index_start = 0;
        if (part_from_index != -1) {
            part_index_start = part_from_index;
        }
    
    
        int part_index_end = this_->m_FileInfo.PartPoolSize;
        if (part_to_index != -1) {
            part_index_end = part_to_index;
        }
        
        for (int i = part_index_start; i < part_index_end; i++) {
            if (i == unk_1) {
                continue;
            }
            
            MUModelPart* part_object = &this_->m_PartPool[i];
    
    
            if (part_object->TrianglePoolSize <= 0 || part_object->Index == unk_0) {
                continue;
            }
            
            glBegin(GL_TRIANGLES);
            for (int j = 0; j < part_object->TrianglePoolSize; j++) {
                MUModelPartTriangle* triangle_object = &part_object->TrianglePool[j];
                
                for (int k = 0; k < triangle_object->field_0; k++) {
                    MUVector3f vertex;
    
    
                    int triangle_world_index = triangle_object->PositionPoolIndex[k];
                    int world_vertex_memory_offset = 0x7702578 + (180000 * i) + (triangle_world_index * 12);
                    MUVector3f* world_vertex = &*(MUVector3f*)world_vertex_memory_offset;
    
    
                    vertex.X = world_vertex->X - this_->field_6C.X;
                    vertex.Y = world_vertex->Y - this_->field_6C.Y;
                    vertex.Z = world_vertex->Z - this_->field_6C.Z;
    
    
                    vertex.X = (vertex.X + width) * vertex.Z / (vertex.Z - height) + vertex.X;
                    
                    vertex.X += this_->field_6C.X;
                    vertex.Y += this_->field_6C.Y;
                    vertex.Z = 5.0f + this_->field_6C.Z + scale;
                    
                    glVertex3fv((GLfloat*)&vertex);
                }
            }
            glEnd();        
        }
    
    
        glPopMatrix();
    
    
        glDisable(GL_BLEND);  
        GameGL_EnableDepthMask();
        
        glDisable(GL_STENCIL_TEST);
    }
    P.S.: easy fix for creation shadows from items


    method in one picture, can be founded with simple calls compare from CreateShadow.
    Last edited by Lerath; 03-12-15 at 03:34 AM.

  7. #7
    Darkness Member Kiosani is offline
    MemberRank
    Oct 2007 Join Date
    ArgentinaLocation
    1,276Posts

    config Re: How improve quality of shadows?

    Quote Originally Posted by Lerath View Post
    so, im not get approval from heaven for continue it's and stop with this result:shadows look really better, but maked only 2 items: transparent, solid rendering of shadow.im not will publish full source code bcz it's not have reason (many research for other main.exe), only 2 functions for understand concept:
    Code:
    // global static functionvoid GameRenderer_RenderGround(int mode) {    glEnable(GL_STENCIL_TEST);    glClear(GL_STENCIL_BUFFER_BIT);         // disable draw in other buffers, will draw only in stencil    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);    glDepthMask(GL_FALSE);        // setup stencil buffer    glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);    imp_GameRenderer_RenderGround(mode); // render ground to stencil    // continue draw stencil only with "1" id & save buffer for continue    glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);    // restore other buffers    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);    glDepthMask(GL_TRUE);        glDisable(GL_STENCIL_TEST);    imp_GameRenderer_RenderGround(mode); // render ground to normal}// class methodvoid CResourceExtension::CreateObjectShadow(MUModelObject* this_, int unk_0, int unk_1, int part_from_index, int part_to_index, int scale) {    if (this_->m_FileInfo.PartPoolSize m_FileInfo.PartPoolSize;    if (part_to_index != -1) {        part_index_end = part_to_index;    }        for (int i = part_index_start; i < part_index_end; i++) {        if (i == unk_1) {            continue;        }                MUModelPart* part_object = &this_->m_PartPool[i];        if (part_object->TrianglePoolSize Index == unk_0) {            continue;        }                glBegin(GL_TRIANGLES);        for (int j = 0; j < part_object->TrianglePoolSize; j++) {            MUModelPartTriangle* triangle_object = &part_object->TrianglePool[j];                        for (int k = 0; k < triangle_object->field_0; k++) {                MUVector3f vertex;                int triangle_world_index = triangle_object->PositionPoolIndex[k];                int world_vertex_memory_offset = 0x7702578 + (180000 * i) + (triangle_world_index * 12);                MUVector3f* world_vertex = &*(MUVector3f*)world_vertex_memory_offset;                vertex.X = world_vertex->X - this_->field_6C.X;                vertex.Y = world_vertex->Y - this_->field_6C.Y;                vertex.Z = world_vertex->Z - this_->field_6C.Z;                vertex.X = (vertex.X + width) * vertex.Z / (vertex.Z - height) + vertex.X;                                vertex.X += this_->field_6C.X;                vertex.Y += this_->field_6C.Y;                vertex.Z = 5.0f + this_->field_6C.Z + scale;                                glVertex3fv((GLfloat*)&vertex);            }        }        glEnd();            }    glPopMatrix();    glDisable(GL_BLEND);      GameGL_EnableDepthMask();        glDisable(GL_STENCIL_TEST);}
    P.S.: easy fix for creation shadows from itemsmethod in one picture, can be founded with simple calls compare from CreateShadow.
    cool work bro, maybe u can the next time create a cool code for draw a nice skydome + atmosphere to use with 3d camera mode.. exists a old: skybox code here in forum.. created using opengl.. and glut lib, but this is old. This is only a idea.

    and a new water shader, in the past I start a work with this, but is difficult.. and the GPU not support some methods on the memory directly modification. :(

    ps: here IDA pseudocode for all from this function recoded for: 1.03k jpn ;)

    Code:
    //----- (004D0AE3) -------------------------------------------------------
    void __thiscall sub_4D0AE3(int this, int a2, int a3, int a4, int a5)
    {
      int v5; // [sp+0h] [bp-38h]@1
      GLfloat v; // [sp+4h] [bp-34h]@17
      float v7; // [sp+8h] [bp-30h]@17
      float v8; // [sp+Ch] [bp-2Ch]@17
      int v9; // [sp+10h] [bp-28h]@17
      int k; // [sp+14h] [bp-24h]@15
      int v11; // [sp+18h] [bp-20h]@15
      int j; // [sp+1Ch] [bp-1Ch]@13
      int v13; // [sp+20h] [bp-18h]@11
      int v14; // [sp+24h] [bp-14h]@2
      float v15; // [sp+28h] [bp-10h]@6
      float v16; // [sp+2Ch] [bp-Ch]@6
      int v17; // [sp+30h] [bp-8h]@2
      int i; // [sp+34h] [bp-4h]@8
    
    
      v5 = this;
      if ( *(_WORD *)(this + 36) )
      {
        sub_5F3ADF(0);
        sub_5F3A7C();
        sub_4CD29C(1065353216);
        v17 = 0;
        v14 = *(_WORD *)(v5 + 36);
        if ( a4 != -1 )
          v17 = a4;
        if ( a5 != -1 )
          v14 = a5;
        v16 = 2000.0;
        v15 = 4000.0;
        if ( (unsigned __int8)sub_4D40C0(dword_8C5CF8) )
        {
          v16 = 2500.0;
          v15 = 4000.0;
        }
        for ( i = v17; i < v14; ++i )
        {
          if ( i != a3 )
          {
            v13 = 80 * i + *(_DWORD *)(v5 + 40);
            if ( (signed int)*(_WORD *)(v13 + 12) > 0 && *(_WORD *)(v13 + 2) != a2 )
            {
              glBegin(4u);
              for ( j = 0; j < *(_WORD *)(v13 + 12); ++j )
              {
                v11 = 36 * j + *(_DWORD *)(v13 + 36);
                for ( k = 0; k < *(_BYTE *)v11; ++k )
                {
                  v9 = *(_WORD *)(v11 + 2 * k + 2);
                  v = *((float *)&dword_5989FEC[45000 * i] + 3 * v9) - *(float *)(v5 + 108);
                  v7 = *((float *)&dword_5989FF0[45000 * i] + 3 * v9) - *(float *)(v5 + 112);
                  v8 = *(&dword_5989FF4[45000 * i] + 3 * v9) - *(float *)(v5 + 116);
                  v = (v + v16) * v8 / (v8 - v15) + v;
                  v8 = 5.0;
                  v = v + *(float *)(v5 + 108);
                  v7 = v7 + *(float *)(v5 + 112);
                  v8 = *(float *)(v5 + 116) + 5.0;
                  glVertex3fv(&v);
                }
              }
              glEnd();
            }
          }
        }
        sub_4CD2AF();
        sub_5F3A5D();
      }
    }
    // 8C5CF8: using guessed type int dword_8C5CF8;
    // 5989FEC: using guessed type int dword_5989FEC[];
    // 5989FF0: using guessed type int dword_5989FF0[];
    Last edited by Kiosani; 06-12-20 at 09:41 PM.

  8. #8
    Member laudaicat is offline
    MemberRank
    Oct 2008 Join Date
    86Posts

    Re: How improve quality of shadows?

    Great to see your work.
    About shadow collision, you shouldn't render ground to set stencil to 1, just clear stencil to 1 on that step. It will improve your cpu.

  9. #9
    Apprentice Lerath is offline
    MemberRank
    Aug 2015 Join Date
    14Posts

    Re: How improve quality of shadows?

    @laudaicat,

    please correct me if i'm wrong:

    when we render ground -
    // enable / disable case for not create mistakes in render proccess when it's continue
    glEnable(GL_STENCIL_TEST);

    glClearStencil(1); // setup index of stencil buffer for clearing
    glClear(GL_STENCIL_BUFFER_BIT); // clearing

    glDisable(GL_STENCIL_TEST);

    <render ground>
    when we render shadow -
    // enable / disable case for not create mistakes in render proccess when it's continue
    glEnable(GL_STENCIL_TEST);

    glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); // always pass
    glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // append mode

    <render shadow>
    glDisable(GL_STENCIL_TEST);

  10. #10
    Member laudaicat is offline
    MemberRank
    Oct 2008 Join Date
    86Posts

    Re: How improve quality of shadows?

    1. Clear stencil - do it before draw all shadow group
    glClearStencil(0); // setup index of stencil buffer for clearing
    glClear(GL_STENCIL_BUFFER_BIT); // clearing


    2. Render shadow
    // enable / disable case for not create mistakes in render proccess when it's continue
    glEnable(GL_STENCIL_TEST);

    glStencilFunc(GL_EQUAL, 0, 0xFFFFFFFF); // pass if first render (stencil ref = 0)
    glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // incease that pixel stencil if shadow pass, now it is 1 and it will fail stencil test later (prevent collision shadow)

    <render shadow>
    glDisable(GL_STENCIL_TEST);

  11. #11

    Re: How improve quality of shadows?

    Can share source code?Thanks
    lol



Advertisement