Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

How improve quality of shadows?

Newbie Spellweaver
Joined
Aug 12, 2015
Messages
14
Reaction score
19
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:
Lerath - How improve quality of shadows? - RaGEZONE Forums


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)
Lerath - How improve quality of shadows? - RaGEZONE Forums


2. shadow does not display weapon / items / wings (it's im understand how fix, np)
Lerath - How improve quality of shadows? - RaGEZONE Forums



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 , 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:
Newbie Spellweaver
Joined
Oct 14, 2008
Messages
85
Reaction score
100
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.
 
Joined
May 26, 2009
Messages
17,308
Reaction score
3,218
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
Lerath - How improve quality of shadows? - RaGEZONE Forums

Lerath - How improve quality of shadows? - RaGEZONE Forums


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.
 
Newbie Spellweaver
Joined
Aug 12, 2015
Messages
14
Reaction score
19
Okay, im get time and start lern guides about stencil buffers in opengl, and result is good:
Lerath - How improve quality of shadows? - RaGEZONE Forums


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
 
Joined
May 26, 2009
Messages
17,308
Reaction score
3,218
Okay, im get time and start lern guides about stencil buffers in opengl, and result is good:
Lerath - How improve quality of shadows? - RaGEZONE Forums


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
 
Newbie Spellweaver
Joined
Aug 12, 2015
Messages
14
Reaction score
19
so, im not get approval from heaven for continue it's and stop with this result:
Lerath - How improve quality of shadows? - RaGEZONE Forums


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
Lerath - How improve quality of shadows? - RaGEZONE Forums


can be founded with simple calls compare from CreateShadow.
 
Last edited:
Joined
Oct 29, 2007
Messages
1,289
Reaction score
1,308
so, im not get approval from heaven for continue it's and stop with this result:
Lerath - How improve quality of shadows? - RaGEZONE Forums
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 items
Lerath - How improve quality of shadows? - RaGEZONE Forums
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:
Newbie Spellweaver
Joined
Oct 14, 2008
Messages
85
Reaction score
100
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.
 
Newbie Spellweaver
Joined
Aug 12, 2015
Messages
14
Reaction score
19
@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);
 
Newbie Spellweaver
Joined
Oct 14, 2008
Messages
85
Reaction score
100
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);
 
Back
Top